Browse Source

Merge branch 'master' into 12.0-development

Alex Szpakowski 4 years ago
parent
commit
b7400892a4

+ 6 - 0
src/common/ios.h

@@ -78,6 +78,12 @@ bool setAudioMixWithOthers(bool mixEnabled);
  **/
  **/
 bool hasBackgroundMusic();
 bool hasBackgroundMusic();
 
 
+/**
+ * Registers notifications to handle and restore audio interruptions
+ **/
+void initAudioSessionInterruptionHandler();
+void destroyAudioSessionInterruptionHandler();
+    
 /**
 /**
  * Gets the area in the window that is safe for UI to render to (not covered by
  * Gets the area in the window that is safe for UI to render to (not covered by
  * the status bar, notch, etc.)
  * the status bar, notch, etc.)

+ 84 - 0
src/common/ios.mm

@@ -28,6 +28,8 @@
 #import <AudioToolbox/AudioServices.h>
 #import <AudioToolbox/AudioServices.h>
 #import <AVFoundation/AVFoundation.h>
 #import <AVFoundation/AVFoundation.h>
 
 
+#include "modules/audio/Audio.h"
+
 #include <vector>
 #include <vector>
 
 
 #include <SDL_events.h>
 #include <SDL_events.h>
@@ -200,6 +202,56 @@ static int dropFileEventFilter(void *userdata, SDL_Event *event)
 	}
 	}
 }
 }
 
 
+@interface LoveAudioInterruptionListener : NSObject
+@end
+
+@implementation LoveAudioInterruptionListener
+
++ (id) shared
+{
+	// thread-safe singleton
+	static dispatch_once_t pred = 0;
+	__strong static id _shared = nil;
+	dispatch_once(&pred, ^{
+			_shared = [[self alloc] init];
+		});
+	return _shared;
+}
+
+- (void)audioSessionInterruption:(NSNotification *)note
+{
+	@synchronized (self)
+	{
+		auto audio = love::Module::getInstance<love::audio::Audio>(love::Module::M_AUDIO);
+		if (!audio)
+		{
+			NSLog(@"LoveAudioInterruptionListener could not get love audio module");
+			return;
+		}
+		NSNumber *type = note.userInfo[AVAudioSessionInterruptionTypeKey];
+		if (type.unsignedIntegerValue == AVAudioSessionInterruptionTypeBegan)
+			audio->pauseContext();
+		else
+			audio->resumeContext();
+	}
+}
+
+- (void)applicationBecameActive:(NSNotification *)note
+{
+	@synchronized (self)
+	{
+		auto audio = love::Module::getInstance<love::audio::Audio>(love::Module::M_AUDIO);
+		if (!audio)
+		{
+			NSLog(@"ERROR:could not get love audio module");
+			return;
+		}
+		audio->resumeContext();
+	}
+}
+
+@end // LoveAudioInterruptionListener
+
 namespace love
 namespace love
 {
 {
 namespace ios
 namespace ios
@@ -380,6 +432,38 @@ bool hasBackgroundMusic()
 	}
 	}
 }
 }
 
 
+void initAudioSessionInterruptionHandler()
+{
+	@autoreleasepool
+	{
+		AVAudioSession *session = [AVAudioSession sharedInstance];
+		NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
+
+		[center addObserver:[LoveAudioInterruptionListener shared]
+			   selector:@selector(audioSessionInterruption:)
+			       name:AVAudioSessionInterruptionNotification
+			     object:session];
+
+		// An interruption end notification is not guaranteed to be sent if
+		// we were previously interrupted... resuming if needed when the app
+		// becomes active seems to be the way to go.
+		[center addObserver:[LoveAudioInterruptionListener shared]
+			   selector:@selector(applicationBecameActive:)
+			       name:UIApplicationDidBecomeActiveNotification
+			     object:nil];
+
+		[center addObserver:[LoveAudioInterruptionListener shared]
+			   selector:@selector(applicationBecameActive:)
+			       name:UIApplicationWillEnterForegroundNotification
+			     object:nil];
+	}
+}
+
+void destroyAudioSessionInterruptionHandler()
+{
+	[[NSNotificationCenter defaultCenter] removeObserver:[LoveAudioInterruptionListener shared]];
+}
+
 Rect getSafeArea(SDL_Window *window)
 Rect getSafeArea(SDL_Window *window)
 {
 {
 	@autoreleasepool
 	@autoreleasepool

+ 6 - 0
src/modules/audio/Audio.h

@@ -291,6 +291,12 @@ public:
 	 **/
 	 **/
 	static bool setMixWithSystem(bool mix);
 	static bool setMixWithSystem(bool mix);
 
 
+	/**
+	 * Pause/resume audio context
+	 */
+	virtual void pauseContext() = 0;
+	virtual void resumeContext() = 0;
+
 private:
 private:
 
 
 	static StringMap<DistanceModel, DISTANCE_MAX_ENUM>::Entry distanceModelEntries[];
 	static StringMap<DistanceModel, DISTANCE_MAX_ENUM>::Entry distanceModelEntries[];

+ 9 - 0
src/modules/audio/null/Audio.cpp

@@ -203,6 +203,15 @@ bool Audio::isEFXsupported() const
 	return false;
 	return false;
 }
 }
 
 
+void Audio::pauseContext()
+{
+}
+
+void Audio::resumeContext()
+{
+}
+
+
 } // null
 } // null
 } // audio
 } // audio
 } // love
 } // love

+ 3 - 0
src/modules/audio/null/Audio.h

@@ -86,6 +86,9 @@ public:
 	int getMaxSourceEffects() const;
 	int getMaxSourceEffects() const;
 	bool isEFXsupported() const;
 	bool isEFXsupported() const;
 
 
+	void pauseContext();
+	void resumeContext();
+
 private:
 private:
 	float volume;
 	float volume;
 	DistanceModel distanceModel;
 	DistanceModel distanceModel;

+ 23 - 0
src/modules/audio/openal/Audio.cpp

@@ -26,6 +26,10 @@
 #include <cstdlib>
 #include <cstdlib>
 #include <iostream>
 #include <iostream>
 
 
+#ifdef LOVE_IOS
+#include "common/ios.h"
+#endif
+
 namespace love
 namespace love
 {
 {
 namespace audio
 namespace audio
@@ -189,10 +193,18 @@ Audio::Audio()
 
 
 	poolThread = new PoolThread(pool);
 	poolThread = new PoolThread(pool);
 	poolThread->start();
 	poolThread->start();
+	
+#ifdef LOVE_IOS
+	love::ios::initAudioSessionInterruptionHandler();
+#endif
+        
 }
 }
 
 
 Audio::~Audio()
 Audio::~Audio()
 {
 {
+#ifdef LOVE_IOS
+	love::ios::destroyAudioSessionInterruptionHandler();
+#endif
 	poolThread->setFinish();
 	poolThread->setFinish();
 	poolThread->wait();
 	poolThread->wait();
 
 
@@ -293,6 +305,17 @@ std::vector<love::audio::Source*> Audio::pause()
 	return Source::pause(pool);
 	return Source::pause(pool);
 }
 }
 
 
+void Audio::pauseContext()
+{
+	alcMakeContextCurrent(nullptr);
+}
+
+void Audio::resumeContext()
+{
+	if (context && alcGetCurrentContext() != context)
+		alcMakeContextCurrent(context);
+}
+
 void Audio::setVolume(float volume)
 void Audio::setVolume(float volume)
 {
 {
 	alListenerf(AL_GAIN, volume);
 	alListenerf(AL_GAIN, volume);

+ 2 - 0
src/modules/audio/openal/Audio.h

@@ -95,6 +95,8 @@ public:
 	void pause(love::audio::Source *source);
 	void pause(love::audio::Source *source);
 	void pause(const std::vector<love::audio::Source*> &sources);
 	void pause(const std::vector<love::audio::Source*> &sources);
 	std::vector<love::audio::Source*> pause();
 	std::vector<love::audio::Source*> pause();
+	void pauseContext();
+	void resumeContext();
 	void setVolume(float volume);
 	void setVolume(float volume);
 	float getVolume() const;
 	float getVolume() const;
 
 

+ 1 - 1
src/modules/graphics/opengl/StreamBuffer.cpp

@@ -499,7 +499,7 @@ love::graphics::StreamBuffer *CreateStreamBuffer(BufferType mode, size_t size)
 		{
 		{
 			// AMD's pinned memory seems to be faster than persistent mapping,
 			// AMD's pinned memory seems to be faster than persistent mapping,
 			// on AMD GPUs.
 			// on AMD GPUs.
-			if (GLAD_AMD_pinned_memory)
+			if (GLAD_AMD_pinned_memory && gl.getVendor() == OpenGL::VENDOR_AMD)
 			{
 			{
 				try
 				try
 				{
 				{