Browse Source

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
Miku AuahDark 3 years ago
parent
commit
3c2b1b888e

+ 39 - 1
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<love::audio::Source*> 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)

+ 11 - 0
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<love::audio::Source*> pausedSources;
+#endif
 }; // Audio
 
 #ifdef ALC_EXT_EFX

+ 2 - 13
src/modules/event/sdl/Event.cpp

@@ -627,20 +627,9 @@ Message *Event::convertWindowEvent(const SDL_Event &e)
 		if (auto audio = Module::getInstance<audio::Audio>(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;

+ 0 - 4
src/modules/event/sdl/Event.h

@@ -78,10 +78,6 @@ private:
 	static std::map<SDL_Keycode, love::keyboard::Keyboard::Key> createKeyMap();
 	static std::map<SDL_Keycode, love::keyboard::Keyboard::Key> keys;
 
-#ifdef LOVE_ANDROID
-	std::vector<love::audio::Source*> pausedSources;
-#endif
-
 }; // Event
 
 } // sdl