From b21c69c60ea821be57053ce38bca0b25de0df493 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois?= Date: Tue, 1 Mar 2022 01:12:11 +0000 Subject: [PATCH] Audio control - play, pause, volume, speed, loop (#3948) # Objective - Add ways to control how audio is played ## Solution - playing a sound will return a (weak) handle to an asset that can be used to control playback - if the asset is dropped, it will detach the sink (same behaviour as now) --- Cargo.toml | 4 + crates/bevy_audio/src/audio.rs | 74 ++++++++++++++- crates/bevy_audio/src/audio_output.rs | 128 ++++++++++++++++++++++++-- crates/bevy_audio/src/lib.rs | 1 + examples/README.md | 1 + examples/audio/audio_control.rs | 65 +++++++++++++ 6 files changed, 258 insertions(+), 15 deletions(-) create mode 100644 examples/audio/audio_control.rs diff --git a/Cargo.toml b/Cargo.toml index f7ca276c55..b14b51b22e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -304,6 +304,10 @@ path = "examples/async_tasks/external_source_external_thread.rs" name = "audio" path = "examples/audio/audio.rs" +[[example]] +name = "audio_control" +path = "examples/audio/audio_control.rs" + # Diagnostics [[example]] name = "log_diagnostics" diff --git a/crates/bevy_audio/src/audio.rs b/crates/bevy_audio/src/audio.rs index 1a8ae32b88..4384175705 100644 --- a/crates/bevy_audio/src/audio.rs +++ b/crates/bevy_audio/src/audio.rs @@ -1,5 +1,5 @@ -use crate::{AudioSource, Decodable}; -use bevy_asset::{Asset, Handle}; +use crate::{AudioSink, AudioSource, Decodable}; +use bevy_asset::{Asset, Handle, HandleId}; use parking_lot::RwLock; use std::{collections::VecDeque, fmt}; @@ -18,7 +18,7 @@ where Source: Asset + Decodable, { /// Queue for playing audio from asset handles - pub queue: RwLock>>, + pub(crate) queue: RwLock>>, } impl fmt::Debug for Audio @@ -55,7 +55,71 @@ where /// audio.play(asset_server.load("my_sound.ogg")); /// } /// ``` - pub fn play(&self, audio_source: Handle) { - self.queue.write().push_front(audio_source); + /// + /// Returns a weak [`Handle`] to the [`AudioSink`]. If this handle isn't changed to a + /// strong one, the sink will be detached and the sound will continue playing. Changing it + /// to a strong handle allows for control on the playback through the [`AudioSink`] asset. + /// + /// ``` + /// # use bevy_ecs::system::Res; + /// # use bevy_asset::{AssetServer, Assets}; + /// # use bevy_audio::{Audio, AudioSink}; + /// fn play_audio_system( + /// asset_server: Res, + /// audio: Res