use crate::{AudioSource, Decodable}; use bevy_asset::{Assets, Handle}; use bevy_ecs::Res; use parking_lot::RwLock; use rodio::{Device, Sink}; use std::collections::VecDeque; /// Used to play audio on the current "audio device" pub struct AudioOutput

where P: Decodable, { device: Device, queue: RwLock>>, } impl

Default for AudioOutput

where P: Decodable, { fn default() -> Self { Self { device: rodio::default_output_device().unwrap(), queue: Default::default(), } } } impl

AudioOutput

where P: Decodable,

::Decoder: rodio::Source + Send + Sync, <

::Decoder as Iterator>::Item: rodio::Sample + Send + Sync, { pub fn play_source(&self, audio_source: &P) { let sink = Sink::new(&self.device); sink.append(audio_source.decoder()); sink.detach(); } pub fn play(&self, audio_source: Handle

) { self.queue.write().push_front(audio_source); } pub fn try_play_queued(&self, audio_sources: &Assets

) { let mut queue = self.queue.write(); let len = queue.len(); let mut i = 0; while i < len { let audio_source_handle = queue.pop_back().unwrap(); if let Some(audio_source) = audio_sources.get(&audio_source_handle) { self.play_source(audio_source); } else { // audio source hasn't loaded yet. add it back to the queue queue.push_front(audio_source_handle); } i += 1; } } } /// Plays audio currently queued in the [AudioOutput] resource pub fn play_queued_audio_system

(audio_sources: Res>, audio_output: Res>) where P: Decodable,

::Decoder: rodio::Source + Send + Sync, <

::Decoder as Iterator>::Item: rodio::Sample + Send + Sync, { audio_output.try_play_queued(&audio_sources); }