use std::{
ffi::c_void,
ops::{Deref, DerefMut},
};
use crate::{arc, cf, define_opts, os};
define_opts!(pub Flags(u32));
impl Flags {
pub const UNSEARCHABLE: Self = Self(1);
pub const SANDBOX_SAFE: Self = Self(2);
pub const IS_V3_AUDIO_UNIT: Self = Self(4);
pub const REQUIRES_ASYNC_INSTANTIATION: Self = Self(8);
pub const CAN_LOAD_IN_PROCESS: Self = Self(0x10);
}
define_opts!(pub InstantiationOpts(u32));
impl InstantiationOpts {
pub const LOAD_OUT_OF_PROCESS: Self = Self(1);
pub const LOAD_IN_PROCESS: Self = Self(2);
pub const LOADED_REMOTELY: Self = Self(1 << 31);
}
#[doc(alias = "AudioComponentDescription")]
#[derive(Default, Debug)]
#[repr(C)]
pub struct Desc {
pub type_: os::Type,
pub sub_type: os::Type,
pub manufacturer: os::Type,
pub flags: u32,
pub flags_mask: u32,
}
impl Desc {
#[doc(alias = "AudioComponentCount")]
pub fn components_count(&self) -> u32 {
unsafe { AudioComponentCount(self) }
}
}
impl IntoIterator for Desc {
type Item = &'static Component;
type IntoIter = Iter;
fn into_iter(self) -> Self::IntoIter {
Iter {
desc: self,
component: None,
}
}
}
pub struct Iter {
desc: Desc,
component: Option<&'static Component>,
}
impl Iterator for Iter {
type Item = &'static Component;
fn next(&mut self) -> Option<Self::Item> {
self.component = unsafe { AudioComponentFindNext(self.component, &self.desc) };
self.component
}
}
#[doc(alias = "AudioComponent")]
#[derive(Debug)]
#[repr(transparent)]
pub struct Component(c_void);
#[doc(alias = "OpaqueAudioComponentInstance")]
#[derive(Debug)]
#[repr(transparent)]
pub struct Instance(c_void);
#[doc(alias = "AudioComponentInstance")]
#[derive(Debug)]
#[repr(transparent)]
pub struct InstanceRef(&'static mut Instance);
pub trait State<T> {
fn release_resources(_instance: &mut T) -> os::Result {
Ok(())
}
}
#[derive(Debug)]
pub struct UninitializedState;
#[derive(Debug)]
pub struct InitializedState;
impl Component {
#[inline]
pub fn name(&self) -> os::Result<arc::R<cf::String>> {
unsafe { os::result_unchecked(|val| AudioComponentCopyName(self, val)) }
}
#[inline]
pub fn desc(&self) -> os::Result<Desc> {
let mut desc = Desc::default();
unsafe { AudioComponentGetDescription(self, &mut desc).result()? };
Ok(desc)
}
#[inline]
pub fn version(&self) -> os::Result<u32> {
let mut version = 0;
unsafe { AudioComponentGetVersion(self, &mut version).result()? };
Ok(version)
}
#[doc(alias = "AudioComponentInstanceNew")]
pub fn open(&self) -> os::Result<InstanceRef> {
let mut instance = None;
unsafe {
AudioComponentInstanceNew(self, &mut instance).result()?;
Ok(InstanceRef(instance.unwrap_unchecked()))
}
}
}
impl Instance {
pub fn component(&self) -> Option<&Component> {
unsafe { AudioComponentInstanceGetComponent(self) }
}
pub unsafe fn dispose(&mut self) -> os::Result {
unsafe { AudioComponentInstanceDispose(self).into() }
}
}
impl Drop for InstanceRef {
fn drop(&mut self) {
let res = unsafe { self.0.dispose() };
debug_assert!(res.is_ok());
}
}
impl Deref for InstanceRef {
type Target = Instance;
fn deref(&self) -> &Self::Target {
self.0
}
}
impl DerefMut for InstanceRef {
fn deref_mut(&mut self) -> &mut Self::Target {
self.0
}
}
unsafe extern "C-unwind" {
fn AudioComponentFindNext(
in_component: Option<&Component>,
in_desc: &Desc,
) -> Option<&'static Component>;
fn AudioComponentCount(in_desc: &Desc) -> u32;
fn AudioComponentCopyName(
in_component: &Component,
out_name: *mut Option<arc::R<cf::String>>,
) -> os::Status;
fn AudioComponentGetDescription(component: &Component, out_desc: &mut Desc) -> os::Status;
fn AudioComponentGetVersion(component: &Component, out_version: &mut u32) -> os::Status;
fn AudioComponentInstanceNew(
component: &Component,
out_instance: *mut Option<&'static mut Instance>,
) -> os::Status;
fn AudioComponentInstanceDispose(instance: &mut Instance) -> os::Status;
fn AudioComponentInstanceGetComponent(instance: &Instance) -> Option<&Component>;
}
#[cfg(test)]
mod tests {
use crate::at::audio;
#[test]
fn basics() {
let desc = audio::ComponentDesc {
..Default::default()
};
let count = desc.components_count();
for c in desc.into_iter() {
let name = c.name().unwrap();
let version = c.version().unwrap();
let desc = c.desc().unwrap();
println!("v. {version}: {name:?}\n {desc:?}");
}
assert!(count > 0);
}
#[test]
fn aac() {
let desc = audio::ComponentDesc {
type_: u32::from_be_bytes(*b"aenc"),
sub_type: u32::from_be_bytes(*b"aac "),
..Default::default()
};
let _inst = desc.into_iter().next().unwrap().open().unwrap();
}
}