From 325721e4d1bd1b13781f12a157a67eacac000500 Mon Sep 17 00:00:00 2001 From: Zicklag Date: Thu, 19 Oct 2023 12:25:51 -0500 Subject: [PATCH] fix: fallback to dummy audio backend if the real audio backend fails. --- .../bones_framework/src/render/audio.rs | 46 +++++++++++++++++-- 1 file changed, 43 insertions(+), 3 deletions(-) diff --git a/framework_crates/bones_framework/src/render/audio.rs b/framework_crates/bones_framework/src/render/audio.rs index eb6a75dc52..f6b7e96fc8 100644 --- a/framework_crates/bones_framework/src/render/audio.rs +++ b/framework_crates/bones_framework/src/render/audio.rs @@ -6,7 +6,10 @@ use crate::prelude::*; pub use kira::{self, sound::static_sound::StaticSoundData}; use kira::{ - manager::{backend::cpal::CpalBackend, AudioManager as KiraAudioManager}, + manager::{ + backend::{cpal::CpalBackend, mock::MockBackend, Backend}, + AudioManager as KiraAudioManager, + }, sound::SoundData, }; @@ -20,10 +23,47 @@ pub fn game_plugin(game: &mut Game) { /// The audio manager resource which can be used to play sounds. #[derive(HasSchema, Deref, DerefMut)] #[schema(no_clone)] -pub struct AudioManager(KiraAudioManager); +pub struct AudioManager(KiraAudioManager); impl Default for AudioManager { fn default() -> Self { - Self(KiraAudioManager::::new(default()).unwrap()) + Self(KiraAudioManager::::new(default()).unwrap()) + } +} + +/// Kira audio backend that will fall back to a dummy backend if setting up the Cpal backend +/// fails with an error. +#[allow(clippy::large_enum_variant)] +pub enum CpalWithFallbackBackend { + /// This is a working Cpal backend. + Cpal(CpalBackend), + /// This is a dummy backend since Cpal didn't work. + Dummy(MockBackend), +} + +impl Backend for CpalWithFallbackBackend { + type Settings = ::Settings; + type Error = ::Error; + + fn setup(settings: Self::Settings) -> Result<(Self, u32), Self::Error> { + match CpalBackend::setup(settings) { + Ok((back, bit)) => Ok((Self::Cpal(back), bit)), + Err(e) => { + tracing::error!("Error starting audio backend, using dummy backend instead: {e}"); + Ok(MockBackend::setup(default()) + .map(|(back, bit)| (Self::Dummy(back), bit)) + .unwrap()) + } + } + } + + fn start(&mut self, renderer: kira::manager::backend::Renderer) -> Result<(), Self::Error> { + match self { + CpalWithFallbackBackend::Cpal(cpal) => cpal.start(renderer), + CpalWithFallbackBackend::Dummy(dummy) => { + dummy.start(renderer).unwrap(); + Ok(()) + } + } } }