mirror of
https://github.com/bevyengine/bevy
synced 2024-11-10 15:14:50 +00:00
Make AudioOutput
a Resource (#6436)
# Objective - Make `AudioOutput` a `Resource`. ## Solution - Do not store `OutputStream` in the struct. - `mem::forget` `OutputStream`. --- ## Changelog ### Added - `AudioOutput` is now a `Resource`. ## Migration Guide - Use `Res<AudioOutput<Source>>` instead of `NonSend<AudioOutput<Source>>`. Same for `Mut` variants.
This commit is contained in:
parent
63f1a9dec8
commit
344a65313f
2 changed files with 17 additions and 6 deletions
|
@ -1,17 +1,28 @@
|
|||
use crate::{Audio, AudioSource, Decodable};
|
||||
use bevy_asset::{Asset, Assets};
|
||||
use bevy_ecs::system::{NonSend, Res, ResMut};
|
||||
use bevy_ecs::system::{Res, ResMut, Resource};
|
||||
use bevy_reflect::TypeUuid;
|
||||
use bevy_utils::tracing::warn;
|
||||
use rodio::{OutputStream, OutputStreamHandle, Sink, Source};
|
||||
use std::marker::PhantomData;
|
||||
|
||||
/// Used internally to play audio on the current "audio device"
|
||||
///
|
||||
/// ## Note
|
||||
///
|
||||
/// Initializing this resource will leak [`rodio::OutputStream`](rodio::OutputStream)
|
||||
/// using [`std::mem::forget`].
|
||||
/// This is done to avoid storing this in the struct (and making this `!Send`)
|
||||
/// while preventing it from dropping (to avoid halting of audio).
|
||||
///
|
||||
/// This is fine when initializing this once (as is default when adding this plugin),
|
||||
/// since the memory cost will be the same.
|
||||
/// However, repeatedly inserting this resource into the app will **leak more memory**.
|
||||
#[derive(Resource)]
|
||||
pub struct AudioOutput<Source = AudioSource>
|
||||
where
|
||||
Source: Decodable,
|
||||
{
|
||||
_stream: Option<OutputStream>,
|
||||
stream_handle: Option<OutputStreamHandle>,
|
||||
phantom: PhantomData<Source>,
|
||||
}
|
||||
|
@ -22,15 +33,15 @@ where
|
|||
{
|
||||
fn default() -> Self {
|
||||
if let Ok((stream, stream_handle)) = OutputStream::try_default() {
|
||||
// We leak `OutputStream` to prevent the audio from stopping.
|
||||
std::mem::forget(stream);
|
||||
Self {
|
||||
_stream: Some(stream),
|
||||
stream_handle: Some(stream_handle),
|
||||
phantom: PhantomData,
|
||||
}
|
||||
} else {
|
||||
warn!("No audio device found.");
|
||||
Self {
|
||||
_stream: None,
|
||||
stream_handle: None,
|
||||
phantom: PhantomData,
|
||||
}
|
||||
|
@ -84,7 +95,7 @@ where
|
|||
|
||||
/// Plays audio currently queued in the [`Audio`] resource through the [`AudioOutput`] resource
|
||||
pub fn play_queued_audio_system<Source: Asset + Decodable>(
|
||||
audio_output: NonSend<AudioOutput<Source>>,
|
||||
audio_output: Res<AudioOutput<Source>>,
|
||||
audio_sources: Option<Res<Assets<Source>>>,
|
||||
mut audio: ResMut<Audio<Source>>,
|
||||
mut sinks: ResMut<Assets<AudioSink>>,
|
||||
|
|
|
@ -50,7 +50,7 @@ pub struct AudioPlugin;
|
|||
|
||||
impl Plugin for AudioPlugin {
|
||||
fn build(&self, app: &mut App) {
|
||||
app.init_non_send_resource::<AudioOutput<AudioSource>>()
|
||||
app.init_resource::<AudioOutput<AudioSource>>()
|
||||
.add_asset::<AudioSource>()
|
||||
.add_asset::<AudioSink>()
|
||||
.init_resource::<Audio<AudioSource>>()
|
||||
|
|
Loading…
Reference in a new issue