From 3c2b1b888e594e42612c9d58a216ffda8ef4bd3b Mon Sep 17 00:00:00 2001 From: Miku AuahDark Date: Fri, 26 Aug 2022 11:45:25 +0800 Subject: [PATCH] Properly pause all audio processing in Android when minimized. This uses ALC_SOFT_pause_device extension which is available since OpenAL-soft 1.16. We guarantee almost 100% availability of this extension since we've been using OpenAL-soft in Android since beginning. Fixes #1828 --- src/modules/audio/openal/Audio.cpp | 40 +++++++++++++++++++++++++++++- src/modules/audio/openal/Audio.h | 11 ++++++++ src/modules/event/sdl/Event.cpp | 15 ++--------- src/modules/event/sdl/Event.h | 4 --- 4 files changed, 52 insertions(+), 18 deletions(-) diff --git a/src/modules/audio/openal/Audio.cpp b/src/modules/audio/openal/Audio.cpp index 68645e351..a1e1c8be9 100644 --- a/src/modules/audio/openal/Audio.cpp +++ b/src/modules/audio/openal/Audio.cpp @@ -195,7 +195,16 @@ Audio::Audio() #ifdef LOVE_IOS love::ios::initAudioSessionInterruptionHandler(); #endif - + +#ifdef LOVE_ANDROID + bool hasPauseDeviceExt = alcIsExtensionPresent(device, "ALC_SOFT_pause_device") == ALC_TRUE; + alcDevicePauseSOFT = hasPauseDeviceExt + ? (LPALCDEVICEPAUSESOFT) alcGetProcAddress(device, "alcDevicePauseSOFT") + : nullptr; + alcDeviceResumeSOFT = hasPauseDeviceExt + ? (LPALCDEVICERESUMESOFT) alcGetProcAddress(device, "alcDeviceResumeSOFT") + : nullptr; +#endif } Audio::~Audio() @@ -305,13 +314,42 @@ std::vector Audio::pause() void Audio::pauseContext() { +#ifdef LOVE_ANDROID + if (alcDevicePauseSOFT) + alcDevicePauseSOFT(device); + else + { + // This is extremely rare case since we're using OpenAL-soft + // in Android and the ALC_SOFT_pause_device has been supported + // since 1.16 + for (auto &src: pausedSources) + src->release(); + pausedSources = pause(); + for (auto &src: pausedSources) + src->retain(); + } +#else alcMakeContextCurrent(nullptr); +#endif } void Audio::resumeContext() { +#ifdef LOVE_ANDROID + if (alcDeviceResumeSOFT) + alcDeviceResumeSOFT(device); + else + { + // Again, this is rare case + play(pausedSources); + for (auto &src: pausedSources) + src->release(); + pausedSources.resize(0); + } +#else if (context && alcGetCurrentContext() != context) alcMakeContextCurrent(context); +#endif } void Audio::setVolume(float volume) diff --git a/src/modules/audio/openal/Audio.h b/src/modules/audio/openal/Audio.h index 02b8a5f51..192df0f6b 100644 --- a/src/modules/audio/openal/Audio.h +++ b/src/modules/audio/openal/Audio.h @@ -176,6 +176,17 @@ private: DistanceModel distanceModel; //float metersPerUnit = 1.0; + +#ifdef LOVE_ANDROID +# undef ALC_SOFT_pause_device +# ifndef ALC_SOFT_pause_device + typedef void (ALC_APIENTRY*LPALCDEVICEPAUSESOFT)(ALCdevice *device); + typedef void (ALC_APIENTRY*LPALCDEVICERESUMESOFT)(ALCdevice *device); +# endif + LPALCDEVICEPAUSESOFT alcDevicePauseSOFT; + LPALCDEVICERESUMESOFT alcDeviceResumeSOFT; + std::vector pausedSources; +#endif }; // Audio #ifdef ALC_EXT_EFX diff --git a/src/modules/event/sdl/Event.cpp b/src/modules/event/sdl/Event.cpp index db0274998..12aa1e019 100644 --- a/src/modules/event/sdl/Event.cpp +++ b/src/modules/event/sdl/Event.cpp @@ -627,20 +627,9 @@ Message *Event::convertWindowEvent(const SDL_Event &e) if (auto audio = Module::getInstance(Module::M_AUDIO)) { if (e.window.event == SDL_WINDOWEVENT_MINIMIZED) - { - for (auto &src : pausedSources) - src->release(); - pausedSources = audio->pause(); - for (auto &src : pausedSources) - src->retain(); - } + audio->pauseContext(); else if (e.window.event == SDL_WINDOWEVENT_RESTORED) - { - audio->play(pausedSources); - for (auto &src : pausedSources) - src->release(); - pausedSources.resize(0); - } + audio->resumeContext(); } #endif break; diff --git a/src/modules/event/sdl/Event.h b/src/modules/event/sdl/Event.h index 31fe3c959..9a7913491 100644 --- a/src/modules/event/sdl/Event.h +++ b/src/modules/event/sdl/Event.h @@ -78,10 +78,6 @@ private: static std::map createKeyMap(); static std::map keys; -#ifdef LOVE_ANDROID - std::vector pausedSources; -#endif - }; // Event } // sdl