use crate::{DefaultRenderer, Frame, Renderer, RendererHandle, SoundHandle};
#[allow(unused_imports)] use crate::Sound;
#[cfg(feature = "cpal")]
use crate::{Backend, Device, StreamSettings};
use parking_lot::{Mutex, MutexGuard};
use std::sync::Arc;
#[derive(Clone)]
pub struct Mixer {
pub renderer: RendererHandle<DefaultRenderer>,
#[cfg(feature = "cpal")]
pub backend: Arc<Mutex<Backend>>,
}
impl Default for Mixer {
fn default() -> Self {
Self::new()
}
}
impl Mixer {
pub fn new() -> Self {
Self {
renderer: DefaultRenderer::default().into(),
#[cfg(feature = "cpal")]
backend: Arc::new(Mutex::new(Backend::new())),
}
}
#[cfg(feature = "cpal")]
#[inline(always)]
pub fn backend(&self) -> MutexGuard<'_, Backend> {
self.backend.lock()
}
#[inline]
pub fn play(&mut self, sound: impl Into<SoundHandle>) -> SoundHandle {
let handle = sound.into();
self.renderer.guard().add_sound(handle.clone());
handle
}
#[inline]
#[cfg(feature = "cpal")]
pub fn handle_errors(&mut self, err_fn: impl FnMut(cpal::StreamError)) {
self.backend().handle_errors(err_fn);
}
#[inline]
#[cfg(feature = "cpal")]
pub fn init(&self) {
self.init_ex(Device::Default, StreamSettings::default());
}
#[cfg(feature = "cpal")]
pub fn init_ex(&self, device: Device, settings: StreamSettings) {
let backend = self.backend.clone();
let renderer = self.renderer.clone();
std::thread::spawn(move || {
let _ = backend
.lock()
.start_audio_thread(device, settings, renderer);
});
}
pub fn wait(&self) {
while !self.renderer.guard().sounds.is_empty() {
std::thread::sleep(std::time::Duration::from_millis(50));
}
}
#[inline]
pub fn is_finished(&self) -> bool {
!self.renderer.guard().has_sounds()
}
#[inline]
pub fn next_frame(&self, sample_rate: u32) -> Frame {
self.renderer.guard().next_frame(sample_rate)
}
}
pub struct RecordMixer {
pub renderer: RendererHandle<DefaultRenderer>,
}
impl Default for RecordMixer {
fn default() -> Self {
Self::new()
}
}
impl RecordMixer {
pub fn new() -> Self {
Self {
renderer: DefaultRenderer::default().into(),
}
}
#[inline]
pub fn play(&self, sound: impl Into<SoundHandle>) -> SoundHandle {
let handle: SoundHandle = sound.into();
self.renderer.guard().add_sound(handle.clone());
handle
}
#[inline]
pub fn is_finished(&self) -> bool {
!self.renderer.guard().has_sounds()
}
pub fn fill_buffer(&self, sample_rate: u32, frames: &mut [Frame]) {
let mut renderer = self.renderer.guard(); for frame in frames {
*frame = renderer.next_frame(sample_rate);
}
}
#[inline]
pub fn next_frame(&self, sample_rate: u32) -> Frame {
self.renderer.guard().next_frame(sample_rate)
}
}