From 841105a9936da4606fbe40c8b15094a03dfdfd88 Mon Sep 17 00:00:00 2001 From: Weihnachtsbaum <140716472+Weihnachtsbaum@users.noreply.github.com> Date: Mon, 26 May 2025 19:50:40 +0200 Subject: [PATCH] Add `AudioSinkPlayback::position` (#19173) # Objective - Allow users to get the playback position of playing audio. ## Solution - Add a `position` method to `AudioSinkPlayback` - Implement it for `AudioSink` and `SpatialAudioSink` ## Testing - Updated `audio_control` example to show playback position --- crates/bevy_audio/src/sinks.rs | 16 ++++++++++++++++ examples/audio/audio_control.rs | 29 ++++++++++++++++++++++++++++- 2 files changed, 44 insertions(+), 1 deletion(-) diff --git a/crates/bevy_audio/src/sinks.rs b/crates/bevy_audio/src/sinks.rs index ed51754f86..1e020d1fd8 100644 --- a/crates/bevy_audio/src/sinks.rs +++ b/crates/bevy_audio/src/sinks.rs @@ -42,6 +42,14 @@ pub trait AudioSinkPlayback { /// No effect if not paused. fn play(&self); + /// Returns the position of the sound that's being played. + /// + /// This takes into account any speedup or delay applied. + /// + /// Example: if you [`set_speed(2.0)`](Self::set_speed) and [`position()`](Self::position) returns *5s*, + /// then the position in the recording is *10s* from its start. + fn position(&self) -> Duration; + /// Attempts to seek to a given position in the current source. /// /// This blocks between 0 and ~5 milliseconds. @@ -181,6 +189,10 @@ impl AudioSinkPlayback for AudioSink { self.sink.play(); } + fn position(&self) -> Duration { + self.sink.get_pos() + } + fn try_seek(&self, pos: Duration) -> Result<(), SeekError> { self.sink.try_seek(pos) } @@ -281,6 +293,10 @@ impl AudioSinkPlayback for SpatialAudioSink { self.sink.play(); } + fn position(&self) -> Duration { + self.sink.get_pos() + } + fn try_seek(&self, pos: Duration) -> Result<(), SeekError> { self.sink.try_seek(pos) } diff --git a/examples/audio/audio_control.rs b/examples/audio/audio_control.rs index 55d60e2083..19bb8c807a 100644 --- a/examples/audio/audio_control.rs +++ b/examples/audio/audio_control.rs @@ -6,7 +6,10 @@ fn main() { App::new() .add_plugins(DefaultPlugins) .add_systems(Startup, setup) - .add_systems(Update, (update_speed, pause, mute, volume)) + .add_systems( + Update, + (update_progress_text, update_speed, pause, mute, volume), + ) .run(); } @@ -16,6 +19,17 @@ fn setup(mut commands: Commands, asset_server: Res) { MyMusic, )); + commands.spawn(( + Text::new(""), + Node { + position_type: PositionType::Absolute, + top: Val::Px(12.0), + left: Val::Px(12.0), + ..default() + }, + ProgressText, + )); + // example instructions commands.spawn(( Text::new("-/=: Volume Down/Up\nSpace: Toggle Playback\nM: Toggle Mute"), @@ -34,10 +48,23 @@ fn setup(mut commands: Commands, asset_server: Res) { #[derive(Component)] struct MyMusic; +#[derive(Component)] +struct ProgressText; + +fn update_progress_text( + music_controller: Single<&AudioSink, With>, + mut progress_text: Single<&mut Text, With>, +) { + progress_text.0 = format!("Progress: {}s", music_controller.position().as_secs_f32()); +} + fn update_speed(music_controller: Query<&AudioSink, With>, time: Res