Permalink
Browse files

Handle iOS audio session interruptions by reinitializing audio

  • Loading branch information...
KentuckyCompass committed Dec 31, 2017
1 parent 8e1ab3f commit d8b3f4af337575a74853c252e42d4b3289eb7c70
Showing with 97 additions and 3 deletions.
  1. +8 −2 Core/System.cpp
  2. +1 −0 Core/System.h
  3. +88 −1 ios/AppDelegate.mm
View
@@ -134,6 +134,13 @@ void Audio_Init() {
}
}
void Audio_Shutdown() {
if (audioInitialized) {
audioInitialized = false;
host->ShutdownSound();
}
}
bool IsOnSeparateCPUThread() {
if (cpuThread != nullptr) {
return cpuThreadID == std::this_thread::get_id();
@@ -290,8 +297,7 @@ void CPU_Shutdown() {
__KernelShutdown();
HLEShutdown();
if (coreParameter.enableSound) {
host->ShutdownSound();
audioInitialized = false; // deleted in ShutdownSound
Audio_Shutdown();
}
pspFileSystem.Shutdown();
mipsr4k.Shutdown();
View
@@ -77,6 +77,7 @@ void PSP_RunLoopFor(int cycles);
void Core_UpdateDebugStats(bool collectStats);
void Audio_Init();
void Audio_Shutdown();
bool IsOnSeparateCPUThread();
bool IsAudioInitialised();
View
@@ -1,21 +1,108 @@
#import "AppDelegate.h"
#import "ViewController.h"
#import "base/NativeApp.h"
#import "Core/System.h"
#import "Core/Config.h"
#import "Common/Log.h"
#import <AVFoundation/AVFoundation.h>
@implementation AppDelegate
// This will be called when the user receives and dismisses a phone call
// or other interruption to the audio session
// Registered in application:didFinishLaunchingWithOptions:
// for AVAudioSessionInterruptionNotification
-(void) handleAudioSessionInterruption:(NSNotification *)notification {
NSNumber *interruptionType = notification.userInfo[AVAudioSessionInterruptionTypeKey];
// Sanity check in case it's somehow not an NSNumber
if (![interruptionType respondsToSelector:@selector(unsignedIntegerValue)]) {
return; // Lets not crash
}
switch ([interruptionType unsignedIntegerValue]) {
case AVAudioSessionInterruptionTypeBegan:
INFO_LOG(SYSTEM, "ios audio session interruption beginning");
if (g_Config.bEnableSound) {
Audio_Shutdown();
}
break;
case AVAudioSessionInterruptionTypeEnded:
INFO_LOG(SYSTEM, "ios audio session interruption ending");
if (g_Config.bEnableSound) {
/*
* Only try to reinit audio if in the foreground, otherwise
* it may fail. Instead, trust that applicationDidBecomeActive
* will do it later.
*/
if ([UIApplication sharedApplication].applicationState == UIApplicationStateActive) {
Audio_Init();
}
}
break;
default:
break;
};
}
// This will be called when the iOS's shared media process was reset
// Registered in application:didFinishLaunchingWithOptions:
// for AVAudioSessionMediaServicesWereResetNotification
-(void) handleMediaServicesWereReset:(NSNotification *)notification {
INFO_LOG(SYSTEM, "ios media services were reset - reinitializing audio");
/*
When media services were reset, Apple recommends:
1) Dispose of orphaned audio objects (such as players, recorders,
converters, or audio queues) and create new ones
2) Reset any internal audio states being tracked, including all
properties of AVAudioSession
3) When appropriate, reactivate the AVAudioSession instance using the
setActive:error: method
We accomplish this by shutting down and reinitializing audio
*/
if (g_Config.bEnableSound) {
Audio_Shutdown();
Audio_Init();
}
}
-(BOOL) application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.viewController = [[ViewController alloc] init];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleAudioSessionInterruption:) name:AVAudioSessionInterruptionNotification object:[AVAudioSession sharedInstance]];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleMediaServicesWereReset:) name:AVAudioSessionMediaServicesWereResetNotification object:nil];
self.window.rootViewController = self.viewController;
[self.window makeKeyAndVisible];
return YES;
}
-(void) dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
-(void) applicationWillResignActive:(UIApplication *)application {
if (g_Config.bEnableSound) {
Audio_Shutdown();
}
NativeMessageReceived("lost_focus", "");
}
-(void) applicationDidBecomeActive:(UIApplication *)application {
if (g_Config.bEnableSound) {
Audio_Init();
}
NativeMessageReceived("got_focus", "");
}
@end
@end

0 comments on commit d8b3f4a

Please sign in to comment.