use std::{cell::Cell, marker::PhantomData, mem::MaybeUninit};
mod node_builder; mod node_flags; pub mod node_graph_builder;
pub mod nodes;
pub mod voice;
use maudio_sys::ffi as sys;
use crate::{
audio::formats::SampleBuffer,
engine::{
node_graph::{node_graph_builder::NodeGraphBuilder, nodes::NodeRef},
AllocationCallbacks, Engine,
},
AsRawRef, Binding, MaResult, MaudioError,
};
pub struct NodeGraph<'a> {
inner: *mut sys::ma_node_graph,
alloc_cb: Option<&'a AllocationCallbacks>,
_not_sync: PhantomData<Cell<()>>,
}
impl Binding for NodeGraph<'_> {
type Raw = *mut sys::ma_node_graph;
fn from_ptr(_raw: Self::Raw) -> Self {
unimplemented!()
}
fn to_raw(&self) -> Self::Raw {
self.inner
}
}
#[derive(Clone, Copy)]
pub struct NodeGraphRef<'e> {
ptr: *mut sys::ma_node_graph,
_engine: PhantomData<&'e mut Engine>,
_not_sync: PhantomData<Cell<()>>,
}
impl Binding for NodeGraphRef<'_> {
type Raw = *mut sys::ma_node_graph;
fn from_ptr(raw: Self::Raw) -> Self {
Self {
ptr: raw,
_engine: PhantomData,
_not_sync: PhantomData,
}
}
fn to_raw(&self) -> Self::Raw {
self.ptr
}
}
pub(crate) mod private_node_graph {
use super::*;
use maudio_sys::ffi as sys;
pub trait NodeGraphPtrProvider<T: ?Sized> {
fn as_node_graph_ptr(t: &T) -> *mut sys::ma_node_graph;
}
pub struct NodeGraphProvider;
pub struct NodeGraphRefProvider;
impl<'a> NodeGraphPtrProvider<NodeGraph<'a>> for NodeGraphProvider {
#[inline]
fn as_node_graph_ptr(t: &NodeGraph) -> *mut sys::ma_node_graph {
t.to_raw()
}
}
impl<'a> NodeGraphPtrProvider<NodeGraphRef<'a>> for NodeGraphRefProvider {
#[inline]
fn as_node_graph_ptr(t: &NodeGraphRef) -> *mut sys::ma_node_graph {
t.to_raw()
}
}
pub fn node_graph_ptr<T: AsNodeGraphPtr + ?Sized>(t: &T) -> *mut sys::ma_node_graph {
<T as AsNodeGraphPtr>::__PtrProvider::as_node_graph_ptr(t)
}
}
#[doc(hidden)]
pub trait AsNodeGraphPtr {
type __PtrProvider: private_node_graph::NodeGraphPtrProvider<Self>;
}
#[doc(hidden)]
impl AsNodeGraphPtr for NodeGraph<'_> {
type __PtrProvider = private_node_graph::NodeGraphProvider;
}
#[doc(hidden)]
impl AsNodeGraphPtr for NodeGraphRef<'_> {
type __PtrProvider = private_node_graph::NodeGraphRefProvider;
}
impl<T: AsNodeGraphPtr + ?Sized> NodeGraphOps for T {}
pub trait NodeGraphOps: AsNodeGraphPtr {
fn endpoint(&self) -> Option<NodeRef<'_>> {
graph_ffi::ma_node_graph_get_endpoint(self)
}
fn read_pcm_frames_into(&mut self, dst: &mut [f32]) -> MaResult<usize> {
graph_ffi::ma_node_graph_read_pcm_frames_into(self, dst)
}
fn read_pcm_frames(&mut self, frame_count: u64) -> MaResult<SampleBuffer<f32>> {
graph_ffi::ma_node_graph_read_pcm_frames(self, frame_count)
}
fn channels(&self) -> u32 {
graph_ffi::ma_node_graph_get_channels(self)
}
fn time(&self) -> u64 {
graph_ffi::ma_node_graph_get_time(self)
}
fn set_time(&mut self, global_time: u64) -> MaResult<()> {
let res = graph_ffi::ma_node_graph_set_time(self, global_time);
MaudioError::check(res)
}
}
impl<'a> NodeGraph<'a> {
fn with_alloc_callbacks(
config: &NodeGraphBuilder,
alloc: Option<&'a AllocationCallbacks>,
) -> MaResult<Self> {
let mut mem: Box<MaybeUninit<sys::ma_node_graph>> = Box::new(MaybeUninit::uninit());
let alloc_cb: *const sys::ma_allocation_callbacks =
alloc.map_or(core::ptr::null(), |c| c.as_raw_ptr());
graph_ffi::ma_node_graph_init(config.as_raw_ptr(), alloc_cb, mem.as_mut_ptr())?;
let inner: *mut sys::ma_node_graph = Box::into_raw(mem) as *mut sys::ma_node_graph;
Ok(Self {
inner,
alloc_cb: alloc,
_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(),
}
}
}
mod graph_ffi {
use maudio_sys::ffi as sys;
use crate::{
audio::formats::SampleBuffer,
engine::node_graph::{nodes::NodeRef, private_node_graph, AsNodeGraphPtr, NodeGraphOps},
Binding, MaResult, MaudioError,
};
#[inline]
pub(crate) fn ma_node_graph_init(
config: *const sys::ma_node_graph_config,
alloc_cb: *const sys::ma_allocation_callbacks,
node_graph: *mut sys::ma_node_graph,
) -> MaResult<()> {
let res = unsafe { sys::ma_node_graph_init(config, alloc_cb, node_graph) };
MaudioError::check(res)
}
#[inline]
pub(crate) fn ma_node_graph_uninit(
node_graph: *mut sys::ma_node_graph,
alloc_cb: *const sys::ma_allocation_callbacks,
) {
unsafe { sys::ma_node_graph_uninit(node_graph, alloc_cb) }
}
#[inline]
pub(crate) fn ma_node_graph_get_endpoint<'a, N: AsNodeGraphPtr + ?Sized>(
node_graph: &'a N,
) -> Option<NodeRef<'a>> {
let ptr = unsafe {
sys::ma_node_graph_get_endpoint(private_node_graph::node_graph_ptr(node_graph))
};
if ptr.is_null() {
None
} else {
Some(NodeRef::from_ptr(ptr))
}
}
#[inline]
pub fn ma_node_graph_read_pcm_frames_into<N: AsNodeGraphPtr + ?Sized>(
node_graph: &mut N,
dst: &mut [f32],
) -> MaResult<usize> {
let channels = node_graph.channels();
let len = dst.len() as u64;
if channels == 0 {
return Err(MaudioError::from_ma_result(sys::ma_result_MA_INVALID_ARGS));
}
let frame_count = len / channels as u64;
let mut frames_read = 0;
let res = unsafe {
sys::ma_node_graph_read_pcm_frames(
private_node_graph::node_graph_ptr(node_graph),
dst.as_mut_ptr() as *mut std::ffi::c_void,
frame_count,
&mut frames_read,
)
};
MaudioError::check(res)?;
Ok(frames_read as usize)
}
#[inline]
pub(crate) fn ma_node_graph_read_pcm_frames<N: AsNodeGraphPtr + ?Sized>(
node_graph: &mut N,
frame_count: u64,
) -> MaResult<SampleBuffer<f32>> {
let channels = node_graph.channels();
let mut buffer = vec![0.0f32; (frame_count * channels as u64) as usize];
let mut frames_read = 0;
let res = unsafe {
sys::ma_node_graph_read_pcm_frames(
private_node_graph::node_graph_ptr(node_graph),
buffer.as_mut_ptr() as *mut std::ffi::c_void,
frame_count,
&mut frames_read,
)
};
MaudioError::check(res)?;
SampleBuffer::<f32>::from_storage(buffer, frames_read as usize, channels)
}
#[inline]
pub(crate) fn ma_node_graph_get_channels<N: AsNodeGraphPtr + ?Sized>(node_graph: &N) -> u32 {
unsafe {
sys::ma_node_graph_get_channels(
private_node_graph::node_graph_ptr(node_graph) as *const _
)
}
}
#[inline]
pub(crate) fn ma_node_graph_get_time<N: AsNodeGraphPtr + ?Sized>(node_graph: &N) -> u64 {
unsafe {
sys::ma_node_graph_get_time(private_node_graph::node_graph_ptr(node_graph) as *const _)
}
}
#[inline]
pub(crate) fn ma_node_graph_set_time<N: AsNodeGraphPtr + ?Sized>(
node_graph: &mut N,
global_time: u64,
) -> i32 {
unsafe {
sys::ma_node_graph_set_time(private_node_graph::node_graph_ptr(node_graph), global_time)
}
}
}
impl<'a> Drop for NodeGraph<'a> {
fn drop(&mut self) {
graph_ffi::ma_node_graph_uninit(self.to_raw(), self.alloc_cb_ptr());
drop(unsafe { Box::from_raw(self.to_raw()) });
}
}