use ffmpeg_next::{ffi::AVAudioFifo, sys};
use std::{ffi::c_void, ptr, sync::Arc};
use miniaudio_aurex as miniaudio;
use crate::engine::AudioFifo;
#[unsafe(no_mangle)]
pub extern "C" fn data_callback(
p_device: *mut miniaudio::ma_device,
p_output: *mut c_void,
_p_input: *const c_void,
frame_count: miniaudio::ma_uint32,
) {
unsafe {
let arc_ptr = (*p_device).pUserData as *const std::sync::Mutex<AudioFifo>;
let arc = Arc::from_raw(arc_ptr); let arc_clone = arc.clone();
let _ = Arc::into_raw(arc);
match arc_clone.try_lock() {
Ok(mut guard) => {
let fifo = guard.0;
let available = sys::av_audio_fifo_size(fifo);
let mut data_ptrs = [p_output as *mut c_void];
let got = if available >= frame_count as i32 {
sys::av_audio_fifo_read(fifo, data_ptrs.as_mut_ptr(), frame_count as i32)
} else {
if available > 0 {
sys::av_audio_fifo_read(fifo, data_ptrs.as_mut_ptr(), available)
} else {
0
}
};
if got < frame_count as i32 {
let bytes_per_sample = sys::av_get_bytes_per_sample(
sys::AVSampleFormat::AV_SAMPLE_FMT_S16
) as usize;
let channels = (*p_device).playback.channels as usize;
let bytes_per_frame = bytes_per_sample * channels;
let written_bytes = got as usize * bytes_per_frame;
let total_bytes = frame_count as usize * bytes_per_frame;
let remaining_bytes = total_bytes.saturating_sub(written_bytes);
ptr::write_bytes(
(p_output as *mut u8).add(written_bytes),
0,
remaining_bytes,
);
}
}
Err(_) => {
let bytes_per_sample = sys::av_get_bytes_per_sample(
sys::AVSampleFormat::AV_SAMPLE_FMT_S16
) as usize;
let channels = (*p_device).playback.channels as usize;
let bytes_per_frame = bytes_per_sample * channels;
let total_bytes = frame_count as usize * bytes_per_frame;
ptr::write_bytes(p_output as *mut u8, 0, total_bytes);
}
}
}
}