feat(audio): implement AAudio C-ABI function bindings

This commit is contained in:
katR 2026-09-29 21:11:40 +05:30
parent 370a13c422
commit 7f6828df0c
3 changed files with 139 additions and 0 deletions

View file

@ -0,0 +1,113 @@
// SPDX-License-Identifier: GPL-3.0-or-later
use super::builder::AAudioStreamBuilder;
use super::pipewire::PipeWireStreamController;
use super::types::{AAudioDirection, AAudioResult};
pub struct AAudioStreamHandle {
pub controller: PipeWireStreamController,
}
#[no_mangle]
pub unsafe extern "C" fn AAudio_createStreamBuilder(
builder: *mut *mut AAudioStreamBuilder,
) -> i32 {
if builder.is_null() {
return AAudioResult::ErrorNull as i32;
}
let b = Box::new(AAudioStreamBuilder::new());
*builder = Box::into_raw(b);
AAudioResult::Ok as i32
}
#[no_mangle]
pub unsafe extern "C" fn AAudioStreamBuilder_setDirection(
builder: *mut AAudioStreamBuilder,
direction: i32,
) {
if let Some(b) = builder.as_mut() {
let dir = if direction == 1 {
AAudioDirection::Input
} else {
AAudioDirection::Output
};
b.set_direction(dir);
}
}
#[no_mangle]
pub unsafe extern "C" fn AAudioStreamBuilder_openStream(
builder: *mut AAudioStreamBuilder,
stream: *mut *mut AAudioStreamHandle,
) -> i32 {
if builder.is_null() || stream.is_null() {
return AAudioResult::ErrorNull as i32;
}
let b = match builder.as_ref() {
Some(val) => val,
None => return AAudioResult::ErrorNull as i32,
};
let controller = PipeWireStreamController::new(b.direction(), b.sample_rate(), b.channel_count());
let handle = Box::new(AAudioStreamHandle { controller });
*stream = Box::into_raw(handle);
AAudioResult::Ok as i32
}
#[no_mangle]
pub unsafe extern "C" fn AAudioStream_requestStart(stream: *mut AAudioStreamHandle) -> i32 {
if let Some(s) = stream.as_mut() {
match s.controller.request_start() {
Ok(()) => AAudioResult::Ok as i32,
Err(e) => e as i32,
}
} else {
AAudioResult::ErrorNull as i32
}
}
#[no_mangle]
pub unsafe extern "C" fn AAudioStream_requestPause(stream: *mut AAudioStreamHandle) -> i32 {
if let Some(s) = stream.as_mut() {
match s.controller.request_pause() {
Ok(()) => AAudioResult::Ok as i32,
Err(e) => e as i32,
}
} else {
AAudioResult::ErrorNull as i32
}
}
#[no_mangle]
pub unsafe extern "C" fn AAudioStream_requestStop(stream: *mut AAudioStreamHandle) -> i32 {
if let Some(s) = stream.as_mut() {
match s.controller.request_stop() {
Ok(()) => AAudioResult::Ok as i32,
Err(e) => e as i32,
}
} else {
AAudioResult::ErrorNull as i32
}
}
#[no_mangle]
pub unsafe extern "C" fn AAudioStream_close(stream: *mut AAudioStreamHandle) -> i32 {
if !stream.is_null() {
let mut handle = Box::from_raw(stream);
handle.controller.close();
AAudioResult::Ok as i32
} else {
AAudioResult::ErrorNull as i32
}
}
#[no_mangle]
pub unsafe extern "C" fn AAudioStreamBuilder_delete(builder: *mut AAudioStreamBuilder) -> i32 {
if !builder.is_null() {
drop(Box::from_raw(builder));
AAudioResult::Ok as i32
} else {
AAudioResult::ErrorNull as i32
}
}

View file

@ -1,5 +1,6 @@
// SPDX-License-Identifier: GPL-3.0-or-later // SPDX-License-Identifier: GPL-3.0-or-later
pub mod builder; pub mod builder;
pub mod buffer; pub mod buffer;
pub mod c_api;
pub mod pipewire; pub mod pipewire;
pub mod types; pub mod types;

View file

@ -0,0 +1,25 @@
// SPDX-License-Identifier: GPL-3.0-or-later
use molotov_core::audio::c_api::*;
use molotov_core::audio::types::{AAudioDirection, AAudioResult};
#[test]
fn test_c_api_stream_lifecycle() {
let mut builder_ptr = std::ptr::null_mut();
unsafe {
let res = AAudio_createStreamBuilder(&mut builder_ptr);
assert_eq!(res, AAudioResult::Ok as i32);
assert!(!builder_ptr.is_null());
AAudioStreamBuilder_setDirection(builder_ptr, AAudioDirection::Input as i32);
let mut stream_ptr = std::ptr::null_mut();
let res = AAudioStreamBuilder_openStream(builder_ptr, &mut stream_ptr);
assert_eq!(res, AAudioResult::Ok as i32);
assert!(!stream_ptr.is_null());
assert_eq!(AAudioStream_requestStart(stream_ptr), AAudioResult::Ok as i32);
assert_eq!(AAudioStream_requestPause(stream_ptr), AAudioResult::Ok as i32);
assert_eq!(AAudioStream_close(stream_ptr), AAudioResult::Ok as i32);
assert_eq!(AAudioStreamBuilder_delete(builder_ptr), AAudioResult::Ok as i32);
}
}