emerald 0.3.214

A lite, fully featured 2D game engine.
Documentation
use crate::{audio::sound::SoundInstanceId, AssetEngine, EmeraldError, SoundKey};

#[cfg(feature = "audio")]
mod kira_backend;

#[cfg(feature = "audio")]
use kira::manager::AudioManager;
#[cfg(feature = "audio")]
use kira_backend::KiraMixer as BackendMixer;

#[cfg(not(feature = "audio"))]
mod dummy;
#[cfg(not(feature = "audio"))]
use dummy::DummyMixer as BackendMixer;

#[cfg(target_arch = "wasm32")]
pub(crate) type ThreadSafeMixer = Box<dyn Mixer>;

#[cfg(not(target_arch = "wasm32"))]
pub(crate) type ThreadSafeMixer = Box<dyn Mixer + Send + Sync>;

pub(crate) trait Mixer {
    fn play(
        &mut self,
        sound: &SoundKey,
        asset_store: &mut AssetEngine,
    ) -> Result<SoundInstanceId, EmeraldError>;
    fn play_and_loop(
        &mut self,
        sound: &SoundKey,
        asset_store: &mut AssetEngine,
    ) -> Result<SoundInstanceId, EmeraldError>;
    fn get_volume(&self) -> Result<f32, EmeraldError>;
    fn set_volume(&mut self, volume: f32) -> Result<(), EmeraldError>;
    fn set_instance_volume(
        &mut self,
        snd_instance_id: SoundInstanceId,
        volume: f32,
    ) -> Result<(), EmeraldError>;
    fn get_instances(&self) -> Result<Vec<SoundInstanceId>, EmeraldError>;
    fn stop(&mut self, snd_instance_id: SoundInstanceId) -> Result<(), EmeraldError>;
    fn pause(&mut self, snd_instance_id: SoundInstanceId) -> Result<(), EmeraldError>;
    fn resume(&mut self, snd_instance_id: SoundInstanceId) -> Result<(), EmeraldError>;
    fn clear(&mut self) -> Result<(), EmeraldError>;
    fn post_update(&mut self) -> Result<(), EmeraldError>;
}

#[cfg(not(feature = "audio"))]
pub(crate) fn new_mixer() -> Result<ThreadSafeMixer, EmeraldError> {
    let mixer = BackendMixer::new()?;

    Ok(mixer)
}

#[cfg(feature = "audio")]
use std::sync::{Arc, Mutex};

#[cfg(feature = "audio")]
static mut KIRA_AUDIO_MANAGER: Option<Arc<Mutex<AudioManager>>> = None;

#[cfg(feature = "audio")]
pub(crate) fn new_mixer() -> Result<ThreadSafeMixer, EmeraldError> {
    use kira::manager::AudioManagerSettings;

    unsafe {
        if KIRA_AUDIO_MANAGER.is_none() {
            let audio_manager = AudioManager::new(AudioManagerSettings {
                num_sounds: 1000,
                num_instances: 1000,
                ..Default::default()
            })?;
            KIRA_AUDIO_MANAGER = Some(Arc::new(Mutex::new(audio_manager)));
        }

        if let Some(audio_manager) = &mut KIRA_AUDIO_MANAGER {
            let mixer = BackendMixer::new(audio_manager.clone())?;

            return Ok(mixer);
        }
    }

    Err(EmeraldError::new(
        "Unable to find or creat the kira audio manager",
    ))
}

pub struct MixerHandler<'a> {
    inner: &'a mut ThreadSafeMixer,
    asset_store: &'a mut AssetEngine,
}
impl<'a> MixerHandler<'a> {
    pub(crate) fn new(inner: &'a mut ThreadSafeMixer, asset_store: &'a mut AssetEngine) -> Self {
        MixerHandler { inner, asset_store }
    }

    pub fn play(&mut self, key: &SoundKey) -> Result<SoundInstanceId, EmeraldError> {
        self.inner.play(key, &mut self.asset_store)
    }
    pub fn play_and_loop(&mut self, key: &SoundKey) -> Result<SoundInstanceId, EmeraldError> {
        self.inner.play_and_loop(key, &mut self.asset_store)
    }
    pub fn get_volume(&self) -> Result<f32, EmeraldError> {
        self.inner.get_volume()
    }
    pub fn set_instance_volume(
        &mut self,
        snd_instance_id: SoundInstanceId,
        volume: f32,
    ) -> Result<(), EmeraldError> {
        self.inner.set_instance_volume(snd_instance_id, volume)
    }
    pub fn set_volume(&mut self, volume: f32) -> Result<(), EmeraldError> {
        self.inner.set_volume(volume)
    }
    pub fn get_instances(&self) -> Result<Vec<SoundInstanceId>, EmeraldError> {
        self.inner.get_instances()
    }
    pub fn stop(&mut self, snd_instance_id: SoundInstanceId) -> Result<(), EmeraldError> {
        self.inner.stop(snd_instance_id)
    }
    pub fn pause(&mut self, snd_instance_id: SoundInstanceId) -> Result<(), EmeraldError> {
        self.inner.pause(snd_instance_id)
    }
    pub fn resume(&mut self, snd_instance_id: SoundInstanceId) -> Result<(), EmeraldError> {
        self.inner.resume(snd_instance_id)
    }
    pub fn clear(&mut self) -> Result<(), EmeraldError> {
        self.inner.clear()
    }
    pub fn clear_sounds(&mut self) -> Result<(), EmeraldError> {
        for instance_id in self.get_instances()? {
            self.stop(instance_id)?;
        }
        Ok(())
    }
}