extern crate alloc;
use core::ffi::c_void;
use windows::Win32::Media::Audio::Apo::{
IApoAcousticEchoCancellation, IApoAuxiliaryInputConfiguration, IApoAuxiliaryInputRT,
IAudioProcessingObject, IAudioProcessingObjectConfiguration, IAudioProcessingObjectRT,
IAudioSystemEffects, IAudioSystemEffects2, IAudioSystemEffects3, APO_REG_PROPERTIES,
};
use windows_core::{ComObject, IUnknown, Interface, GUID, HRESULT};
use crate::aec::class_factory::{AecApoClassFactory, AecApoVTable};
use crate::clsid::Clsid;
use crate::error::HResult;
fn aec_supported_interfaces() -> [GUID; 9] {
[
IAudioProcessingObject::IID,
IAudioProcessingObjectConfiguration::IID,
IAudioProcessingObjectRT::IID,
IAudioSystemEffects::IID,
IAudioSystemEffects2::IID,
IAudioSystemEffects3::IID,
IApoAcousticEchoCancellation::IID,
IApoAuxiliaryInputConfiguration::IID,
IApoAuxiliaryInputRT::IID,
]
}
pub unsafe fn aec_dll_get_class_object_dispatch(
rclsid: *const GUID,
riid: *const GUID,
ppv: *mut *mut c_void,
registry: &[&'static AecApoVTable],
) -> HRESULT {
if ppv.is_null() {
return HResult::E_POINTER.into();
}
unsafe {
*ppv = core::ptr::null_mut();
}
if rclsid.is_null() || riid.is_null() {
return HResult::E_POINTER.into();
}
let requested = Clsid::from(unsafe { *rclsid });
let Some(vtable) = registry.iter().find(|v| v.clsid == requested) else {
return HResult::CLASS_E_CLASSNOTAVAILABLE.into();
};
let factory = AecApoClassFactory::new(vtable);
let com = ComObject::new(factory);
let unknown: IUnknown = com.into_interface();
unsafe { unknown.query(riid, ppv) }
}
pub fn aec_dll_register_server_dispatch(registry: &[&'static AecApoVTable]) -> HRESULT {
let dll_path = match crate::raw::exports::own_module_path() {
Ok(p) => p,
Err(e) => return e.code(),
};
for vtable in registry {
if let Err(e) =
crate::raw::register::write_registry_with(vtable.clsid, vtable.name, &dll_path)
{
return e.code();
}
}
HRESULT(0)
}
pub fn aec_dll_unregister_server_dispatch(registry: &[&'static AecApoVTable]) -> HRESULT {
for vtable in registry {
if let Err(e) = crate::raw::register::clear_registry(&vtable.clsid) {
return e.code();
}
}
HRESULT(0)
}
pub fn build_aec_registration_properties(
instance: &dyn crate::instance::AnyApoInstance,
) -> windows_core::Result<*mut APO_REG_PROPERTIES> {
crate::raw::reg_properties::build_registration_properties_with(
instance,
&aec_supported_interfaces(),
)
}