use std::{cell::Cell, marker::PhantomData, sync::Arc};
use maudio_sys::ffi as sys;
use crate::{
engine::{
node_graph::{node_builder::NodeState, NodeGraph, NodeGraphRef},
AllocationCallbacks,
},
AsRawRef, Binding, MaResult,
};
pub mod effects;
pub mod filters;
pub mod routing;
pub mod source;
struct Node<'a> {
inner: *mut sys::ma_node,
alloc_cb: Option<Arc<AllocationCallbacks>>,
_marker: PhantomData<&'a NodeGraph>,
_not_sync: PhantomData<Cell<()>>,
}
impl Binding for Node<'_> {
type Raw = *mut sys::ma_node;
fn from_ptr(_raw: Self::Raw) -> Self {
unimplemented!()
}
fn to_raw(&self) -> Self::Raw {
self.inner
}
}
#[derive(Clone, Copy)]
pub struct NodeRef<'a> {
ptr: *mut sys::ma_node,
_marker: PhantomData<&'a ()>,
_not_sync: PhantomData<Cell<()>>,
}
impl Binding for NodeRef<'_> {
type Raw = *mut sys::ma_node;
fn from_ptr(raw: Self::Raw) -> Self {
Self {
ptr: raw,
_marker: PhantomData,
_not_sync: PhantomData,
}
}
fn to_raw(&self) -> Self::Raw {
self.ptr
}
}
pub(crate) mod private_node {
use crate::{
data_source::AsSourcePtr,
engine::node_graph::nodes::{
effects::delay::DelayNode,
filters::{
biquad::BiquadNode, hishelf::HiShelfNode, hpf::HpfNode, loshelf::LoShelfNode,
lpf::LpfNode, notch::NotchNode, peak::PeakNode,
},
routing::splitter::SplitterNode,
source::source_node::{AttachedSourceNode, SourceNode},
},
};
use super::*;
use maudio_sys::ffi as sys;
pub trait NodePtrProvider<T: ?Sized> {
fn as_node_ptr(t: &T) -> *mut sys::ma_node;
}
pub struct NodeProvider;
pub struct NodeRefProvider;
pub struct DelayNodeProvider;
pub struct BiquadNodeProvider;
pub struct HiShelfNodeProvider;
pub struct HpfNodeProvider;
pub struct LoShelfNodeProvider;
pub struct LpfNodeProvider;
pub struct NotchNodeProvider;
pub struct PeakNodeProvider;
pub struct SplitterNodeProvider;
pub struct SourceNodeProvider;
pub struct AttachedSourceNodeProvider;
impl<'a> NodePtrProvider<Node<'a>> for NodeProvider {
#[inline]
fn as_node_ptr(t: &Node) -> *mut sys::ma_node {
t.to_raw()
}
}
impl<'a> NodePtrProvider<NodeRef<'a>> for NodeRefProvider {
#[inline]
fn as_node_ptr(t: &NodeRef<'a>) -> *mut sys::ma_node {
t.to_raw()
}
}
impl<'a> NodePtrProvider<DelayNode<'a>> for DelayNodeProvider {
#[inline]
fn as_node_ptr(t: &DelayNode<'a>) -> *mut sys::ma_node {
t.as_node().to_raw()
}
}
impl<'a> NodePtrProvider<BiquadNode<'a>> for BiquadNodeProvider {
#[inline]
fn as_node_ptr(t: &BiquadNode<'a>) -> *mut sys::ma_node {
t.as_node().to_raw()
}
}
impl<'a> NodePtrProvider<HiShelfNode<'a>> for HiShelfNodeProvider {
#[inline]
fn as_node_ptr(t: &HiShelfNode<'a>) -> *mut sys::ma_node {
t.as_node().to_raw()
}
}
impl<'a> NodePtrProvider<HpfNode<'a>> for HpfNodeProvider {
#[inline]
fn as_node_ptr(t: &HpfNode<'a>) -> *mut sys::ma_node {
t.as_node().to_raw()
}
}
impl<'a> NodePtrProvider<LoShelfNode<'a>> for LoShelfNodeProvider {
#[inline]
fn as_node_ptr(t: &LoShelfNode<'a>) -> *mut sys::ma_node {
t.as_node().to_raw()
}
}
impl<'a> NodePtrProvider<LpfNode<'a>> for LpfNodeProvider {
#[inline]
fn as_node_ptr(t: &LpfNode<'a>) -> *mut sys::ma_node {
t.as_node().to_raw()
}
}
impl<'a> NodePtrProvider<NotchNode<'a>> for NotchNodeProvider {
#[inline]
fn as_node_ptr(t: &NotchNode<'a>) -> *mut sys::ma_node {
t.as_node().to_raw()
}
}
impl<'a> NodePtrProvider<PeakNode<'a>> for PeakNodeProvider {
#[inline]
fn as_node_ptr(t: &PeakNode<'a>) -> *mut sys::ma_node {
t.as_node().to_raw()
}
}
impl<'a> NodePtrProvider<SplitterNode<'a>> for SplitterNodeProvider {
#[inline]
fn as_node_ptr(t: &SplitterNode<'a>) -> *mut sys::ma_node {
t.as_node().to_raw()
}
}
impl<'a> NodePtrProvider<SourceNode<'a>> for SourceNodeProvider {
#[inline]
fn as_node_ptr(t: &SourceNode<'a>) -> *mut sys::ma_node {
t.as_node().to_raw()
}
}
impl<'a, S: AsSourcePtr> NodePtrProvider<AttachedSourceNode<'a, S>> for AttachedSourceNodeProvider {
#[inline]
fn as_node_ptr(t: &AttachedSourceNode<'a, S>) -> *mut sys::ma_node {
t.as_node().to_raw()
}
}
pub fn node_ptr<T: AsNodePtr + ?Sized>(t: &T) -> *mut sys::ma_node {
<T as AsNodePtr>::__PtrProvider::as_node_ptr(t)
}
}
#[doc(hidden)]
pub trait AsNodePtr {
type __PtrProvider: private_node::NodePtrProvider<Self>;
}
#[doc(hidden)]
impl<'a> AsNodePtr for Node<'a> {
type __PtrProvider = private_node::NodeProvider;
}
#[doc(hidden)]
impl AsNodePtr for NodeRef<'_> {
type __PtrProvider = private_node::NodeRefProvider;
}
impl<T: AsNodePtr + ?Sized> NodeOps for T {}
pub trait NodeOps: AsNodePtr {
fn attach_output_bus<P: AsNodePtr + ?Sized>(
&mut self,
output_bus: u32,
other_node: &mut P,
other_node_input_bus: u32,
) -> MaResult<()> {
node_ffi::ma_node_attach_output_bus(self, output_bus, other_node, other_node_input_bus)
}
fn detach_output_bus(&mut self, output_bus: u32) -> MaResult<()> {
node_ffi::ma_node_detach_output_bus(self, output_bus)
}
fn detach_all_outputs(&mut self) -> MaResult<()> {
node_ffi::ma_node_detach_all_output_buses(self)
}
fn node_graph(&self) -> Option<NodeGraphRef<'_>> {
node_ffi::ma_node_get_node_graph(self)
}
fn in_bus_count(&self) -> u32 {
node_ffi::ma_node_get_input_bus_count(self)
}
fn out_bus_count(&self) -> u32 {
node_ffi::ma_node_get_output_bus_count(self)
}
fn input_channels(&self, in_bus_index: u32) -> u32 {
node_ffi::ma_node_get_input_channels(self, in_bus_index)
}
fn output_channels(&self, out_bus_index: u32) -> u32 {
node_ffi::ma_node_get_output_channels(self, out_bus_index)
}
fn output_bus_volume(&mut self, out_bux_index: u32) -> f32 {
node_ffi::ma_node_get_output_bus_volume(self, out_bux_index)
}
fn set_output_bus_volume(&mut self, out_bux_index: u32, volume: f32) -> MaResult<()> {
node_ffi::ma_node_set_output_bus_volume(self, out_bux_index, volume)
}
fn state(&self) -> MaResult<NodeState> {
node_ffi::ma_node_get_state(self)
}
fn set_state(&mut self, state: NodeState) -> MaResult<()> {
node_ffi::ma_node_set_state(self, state)
}
fn state_time(&self, state: NodeState) -> u64 {
node_ffi::ma_node_get_state_time(self, state)
}
fn set_state_time(&mut self, state: NodeState, global_time: u64) -> MaResult<()> {
node_ffi::ma_node_set_state_time(self, state, global_time)
}
fn state_by_time(&self, global_time: u64) -> MaResult<NodeState> {
node_ffi::ma_node_get_state_by_time(self, global_time)
}
fn state_by_time_range(
&self,
global_time_beg: u64,
global_time_end: u64,
) -> MaResult<NodeState> {
node_ffi::ma_node_get_state_by_time_range(self, global_time_beg, global_time_end)
}
fn time(&self) -> u64 {
node_ffi::ma_node_get_time(self)
}
fn set_time(&mut self, local_time: u64) -> MaResult<()> {
node_ffi::ma_node_set_time(self, local_time)
}
}
impl<'a> Node<'a> {
pub(crate) fn new(
inner: *mut sys::ma_node,
alloc_cb: Option<Arc<AllocationCallbacks>>,
) -> Self {
Self {
inner,
alloc_cb,
_marker: PhantomData,
_not_sync: PhantomData,
}
}
#[inline]
fn alloc_cb_ptr(&self) -> *const sys::ma_allocation_callbacks {
match &self.alloc_cb {
Some(cb) => cb.as_raw_ptr(),
None => core::ptr::null(),
}
}
}
pub(crate) unsafe extern "C" fn on_get_required_input_frame_count(
_node: *mut sys::ma_node,
out_frames_count: u32,
in_frame_count: *mut u32,
) -> sys::ma_result {
if !in_frame_count.is_null() {
*in_frame_count = out_frames_count;
}
sys::ma_result_MA_SUCCESS
}
pub(super) mod node_ffi {
use maudio_sys::ffi as sys;
use crate::{
engine::node_graph::{
node_builder::NodeState,
nodes::{private_node, AsNodePtr, Node},
NodeGraph, NodeGraphRef,
},
Binding, MaResult, MaudioError,
};
#[inline]
pub(crate) fn ma_node_get_heap_size(
node_graph: &mut NodeGraph,
config: *const sys::ma_node_config,
) -> usize {
let mut heap_size: usize = 0;
unsafe { sys::ma_node_get_heap_size(node_graph.to_raw(), config, &mut heap_size) };
heap_size
}
#[inline]
pub(crate) fn ma_node_init_preallocated(
node_graph: &mut NodeGraph,
config: *const sys::ma_node_config,
heap: *mut core::ffi::c_void,
node: *mut sys::ma_node,
) -> sys::ma_result {
unsafe { sys::ma_node_init_preallocated(node_graph.to_raw(), config, heap, node) }
}
#[inline]
pub(crate) fn ma_node_init(
node_graph: &NodeGraph,
config: *const sys::ma_node_config,
allocation_callbacks: *const sys::ma_allocation_callbacks,
node: *mut sys::ma_node,
) -> MaResult<()> {
let res =
unsafe { sys::ma_node_init(node_graph.to_raw(), config, allocation_callbacks, node) };
MaudioError::check(res)
}
#[inline]
fn ma_node_uninit(node: &mut Node, allocation_callbacks: *const sys::ma_allocation_callbacks) {
unsafe { sys::ma_node_uninit(node.to_raw(), allocation_callbacks) }
}
#[inline]
pub(crate) fn ma_node_get_node_graph<'a, P: AsNodePtr + ?Sized>(
node: &'a P,
) -> Option<NodeGraphRef<'a>> {
let ptr = unsafe { sys::ma_node_get_node_graph(private_node::node_ptr(node) as *const _) };
if ptr.is_null() {
None
} else {
Some(NodeGraphRef::from_ptr(ptr))
}
}
#[inline]
pub(crate) fn ma_node_get_input_bus_count<P: AsNodePtr + ?Sized>(node: &P) -> u32 {
unsafe { sys::ma_node_get_input_bus_count(private_node::node_ptr(node) as *const _) }
}
#[inline]
pub(crate) fn ma_node_get_output_bus_count<P: AsNodePtr + ?Sized>(node: &P) -> u32 {
unsafe { sys::ma_node_get_output_bus_count(private_node::node_ptr(node) as *const _) }
}
#[inline]
pub(crate) fn ma_node_get_input_channels<P: AsNodePtr + ?Sized>(
node: &P,
input_bus_index: u32,
) -> u32 {
unsafe {
sys::ma_node_get_input_channels(
private_node::node_ptr(node) as *const _,
input_bus_index,
)
}
}
#[inline]
pub(crate) fn ma_node_get_output_channels<P: AsNodePtr + ?Sized>(
node: &P,
output_bus_index: u32,
) -> u32 {
unsafe {
sys::ma_node_get_output_channels(
private_node::node_ptr(node) as *const _,
output_bus_index,
)
}
}
#[inline]
pub(crate) fn ma_node_attach_output_bus<P: AsNodePtr + ?Sized, Q: AsNodePtr + ?Sized>(
node: &mut P,
output_bus_index: u32,
other_node: &mut Q,
other_node_input_bus_index: u32,
) -> MaResult<()> {
unsafe {
let res = sys::ma_node_attach_output_bus(
private_node::node_ptr(node),
output_bus_index,
private_node::node_ptr(other_node),
other_node_input_bus_index,
);
MaudioError::check(res)
}
}
#[inline]
pub(crate) fn ma_node_detach_output_bus<P: AsNodePtr + ?Sized>(
node: &mut P,
output_bus_index: u32,
) -> MaResult<()> {
let res = unsafe {
sys::ma_node_detach_output_bus(private_node::node_ptr(node), output_bus_index)
};
MaudioError::check(res)
}
#[inline]
pub(crate) fn ma_node_detach_all_output_buses<P: AsNodePtr + ?Sized>(
node: &mut P,
) -> MaResult<()> {
let res = unsafe { sys::ma_node_detach_all_output_buses(private_node::node_ptr(node)) };
MaudioError::check(res)
}
#[inline]
pub(crate) fn ma_node_set_output_bus_volume<P: AsNodePtr + ?Sized>(
node: &mut P,
output_bus_index: sys::ma_uint32,
volume: f32,
) -> MaResult<()> {
let res = unsafe {
sys::ma_node_set_output_bus_volume(
private_node::node_ptr(node),
output_bus_index,
volume,
)
};
MaudioError::check(res)
}
#[inline]
pub(crate) fn ma_node_get_output_bus_volume<P: AsNodePtr + ?Sized>(
node: &mut P,
output_bus_index: sys::ma_uint32,
) -> f32 {
unsafe {
sys::ma_node_get_output_bus_volume(private_node::node_ptr(node), output_bus_index)
}
}
#[inline]
pub(crate) fn ma_node_set_state<P: AsNodePtr + ?Sized>(
node: &mut P,
state: NodeState,
) -> MaResult<()> {
let res = unsafe { sys::ma_node_set_state(private_node::node_ptr(node), state.into()) };
MaudioError::check(res)
}
#[inline]
pub(crate) fn ma_node_get_state<P: AsNodePtr + ?Sized>(node: &P) -> MaResult<NodeState> {
let res = unsafe { sys::ma_node_get_state(private_node::node_ptr(node) as *const _) };
res.try_into()
}
#[inline]
pub(crate) fn ma_node_set_state_time<P: AsNodePtr + ?Sized>(
node: &mut P,
state: NodeState,
global_time: u64,
) -> MaResult<()> {
let res = unsafe {
sys::ma_node_set_state_time(private_node::node_ptr(node), state.into(), global_time)
};
MaudioError::check(res)
}
#[inline]
pub(crate) fn ma_node_get_state_time<P: AsNodePtr + ?Sized>(node: &P, state: NodeState) -> u64 {
unsafe {
sys::ma_node_get_state_time(private_node::node_ptr(node) as *const _, state.into())
}
}
#[inline]
pub(crate) fn ma_node_get_state_by_time<P: AsNodePtr + ?Sized>(
node: &P,
global_time: u64,
) -> MaResult<NodeState> {
let res = unsafe {
sys::ma_node_get_state_by_time(private_node::node_ptr(node) as *const _, global_time)
};
res.try_into()
}
#[inline]
pub(crate) fn ma_node_get_state_by_time_range<P: AsNodePtr + ?Sized>(
node: &P,
global_time_beg: u64,
global_time_end: u64,
) -> MaResult<NodeState> {
unsafe {
let res = sys::ma_node_get_state_by_time_range(
private_node::node_ptr(node) as *const _,
global_time_beg,
global_time_end,
);
res.try_into()
}
}
#[inline]
pub(crate) fn ma_node_get_time<P: AsNodePtr + ?Sized>(node: &P) -> u64 {
unsafe { sys::ma_node_get_time(private_node::node_ptr(node) as *const _) }
}
#[inline]
pub(crate) fn ma_node_set_time<P: AsNodePtr + ?Sized>(
node: &mut P,
local_time: u64,
) -> MaResult<()> {
let res = unsafe { sys::ma_node_set_time(private_node::node_ptr(node), local_time) };
MaudioError::check(res)
}
}