Resume audio on iOS after phone call or alarm
When a phone call or an alarm triggers on iOS, the application receives
an "audio interruption" and it's up to the application to resume
playback when the interruption ends. I added handling for audio
interruptions same as if the game is focused out and then back in.
(cherry picked from commit 96301e934d
)
This commit is contained in:
parent
db76c54117
commit
ecb4c4268c
|
@ -217,13 +217,24 @@ void AudioDriverCoreAudio::start() {
|
||||||
if (!active) {
|
if (!active) {
|
||||||
OSStatus result = AudioOutputUnitStart(audio_unit);
|
OSStatus result = AudioOutputUnitStart(audio_unit);
|
||||||
if (result != noErr) {
|
if (result != noErr) {
|
||||||
ERR_PRINT("AudioOutputUnitStart failed");
|
ERR_PRINT(("AudioOutputUnitStart failed, code: " + itos(result)).utf8().get_data());
|
||||||
} else {
|
} else {
|
||||||
active = true;
|
active = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void AudioDriverCoreAudio::stop() {
|
||||||
|
if (active) {
|
||||||
|
OSStatus result = AudioOutputUnitStop(audio_unit);
|
||||||
|
if (result != noErr) {
|
||||||
|
ERR_PRINT(("AudioOutputUnitStop failed, code: " + itos(result)).utf8().get_data());
|
||||||
|
} else {
|
||||||
|
active = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int AudioDriverCoreAudio::get_mix_rate() const {
|
int AudioDriverCoreAudio::get_mix_rate() const {
|
||||||
return mix_rate;
|
return mix_rate;
|
||||||
};
|
};
|
||||||
|
|
|
@ -90,6 +90,7 @@ public:
|
||||||
virtual void finish();
|
virtual void finish();
|
||||||
|
|
||||||
bool try_lock();
|
bool try_lock();
|
||||||
|
void stop();
|
||||||
|
|
||||||
AudioDriverCoreAudio();
|
AudioDriverCoreAudio();
|
||||||
~AudioDriverCoreAudio();
|
~AudioDriverCoreAudio();
|
||||||
|
|
|
@ -37,6 +37,7 @@
|
||||||
@interface AppDelegate : NSObject <UIApplicationDelegate, GLViewDelegate> {
|
@interface AppDelegate : NSObject <UIApplicationDelegate, GLViewDelegate> {
|
||||||
//@property (strong, nonatomic) UIWindow *window;
|
//@property (strong, nonatomic) UIWindow *window;
|
||||||
ViewController *view_controller;
|
ViewController *view_controller;
|
||||||
|
bool is_focus_out;
|
||||||
};
|
};
|
||||||
|
|
||||||
@property(strong, nonatomic) UIWindow *window;
|
@property(strong, nonatomic) UIWindow *window;
|
||||||
|
|
|
@ -140,6 +140,42 @@ void _ios_add_joystick(GCController *controller, AppDelegate *delegate) {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void on_focus_out(ViewController *view_controller, bool *is_focus_out) {
|
||||||
|
if (!*is_focus_out) {
|
||||||
|
*is_focus_out = true;
|
||||||
|
if (OS::get_singleton()->get_main_loop())
|
||||||
|
OS::get_singleton()->get_main_loop()->notification(
|
||||||
|
MainLoop::NOTIFICATION_WM_FOCUS_OUT);
|
||||||
|
|
||||||
|
[view_controller.view stopAnimation];
|
||||||
|
if (OS::get_singleton()->native_video_is_playing()) {
|
||||||
|
OSIPhone::get_singleton()->native_video_focus_out();
|
||||||
|
}
|
||||||
|
|
||||||
|
AudioDriverCoreAudio *audio = dynamic_cast<AudioDriverCoreAudio *>(AudioDriverCoreAudio::get_singleton());
|
||||||
|
if (audio)
|
||||||
|
audio->stop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void on_focus_in(ViewController *view_controller, bool *is_focus_out) {
|
||||||
|
if (*is_focus_out) {
|
||||||
|
*is_focus_out = false;
|
||||||
|
if (OS::get_singleton()->get_main_loop())
|
||||||
|
OS::get_singleton()->get_main_loop()->notification(
|
||||||
|
MainLoop::NOTIFICATION_WM_FOCUS_IN);
|
||||||
|
|
||||||
|
[view_controller.view startAnimation];
|
||||||
|
if (OSIPhone::get_singleton()->native_video_is_playing()) {
|
||||||
|
OSIPhone::get_singleton()->native_video_unpause();
|
||||||
|
}
|
||||||
|
|
||||||
|
AudioDriverCoreAudio *audio = dynamic_cast<AudioDriverCoreAudio *>(AudioDriverCoreAudio::get_singleton());
|
||||||
|
if (audio)
|
||||||
|
audio->start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
- (void)controllerWasConnected:(NSNotification *)notification {
|
- (void)controllerWasConnected:(NSNotification *)notification {
|
||||||
// create our dictionary if we don't have one yet
|
// create our dictionary if we don't have one yet
|
||||||
if (ios_joysticks == nil) {
|
if (ios_joysticks == nil) {
|
||||||
|
@ -569,6 +605,8 @@ static int frame_count = 0;
|
||||||
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
|
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
|
||||||
CGRect rect = [[UIScreen mainScreen] bounds];
|
CGRect rect = [[UIScreen mainScreen] bounds];
|
||||||
|
|
||||||
|
is_focus_out = false;
|
||||||
|
|
||||||
[application setStatusBarHidden:YES withAnimation:UIStatusBarAnimationNone];
|
[application setStatusBarHidden:YES withAnimation:UIStatusBarAnimationNone];
|
||||||
// disable idle timer
|
// disable idle timer
|
||||||
// application.idleTimerDisabled = YES;
|
// application.idleTimerDisabled = YES;
|
||||||
|
@ -628,6 +666,12 @@ static int frame_count = 0;
|
||||||
|
|
||||||
[self initGameControllers];
|
[self initGameControllers];
|
||||||
|
|
||||||
|
[[NSNotificationCenter defaultCenter]
|
||||||
|
addObserver:self
|
||||||
|
selector:@selector(onAudioInterruption:)
|
||||||
|
name:AVAudioSessionInterruptionNotification
|
||||||
|
object:[AVAudioSession sharedInstance]];
|
||||||
|
|
||||||
// OSIPhone::screen_width = rect.size.width - rect.origin.x;
|
// OSIPhone::screen_width = rect.size.width - rect.origin.x;
|
||||||
// OSIPhone::screen_height = rect.size.height - rect.origin.y;
|
// OSIPhone::screen_height = rect.size.height - rect.origin.y;
|
||||||
|
|
||||||
|
@ -639,6 +683,18 @@ static int frame_count = 0;
|
||||||
return TRUE;
|
return TRUE;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
- (void)onAudioInterruption:(NSNotification *)notification {
|
||||||
|
if ([notification.name isEqualToString:AVAudioSessionInterruptionNotification]) {
|
||||||
|
if ([[notification.userInfo valueForKey:AVAudioSessionInterruptionTypeKey] isEqualToNumber:[NSNumber numberWithInt:AVAudioSessionInterruptionTypeBegan]]) {
|
||||||
|
NSLog(@"Audio interruption began");
|
||||||
|
on_focus_out(view_controller, &is_focus_out);
|
||||||
|
} else if ([[notification.userInfo valueForKey:AVAudioSessionInterruptionTypeKey] isEqualToNumber:[NSNumber numberWithInt:AVAudioSessionInterruptionTypeEnded]]) {
|
||||||
|
NSLog(@"Audio interruption ended");
|
||||||
|
on_focus_in(view_controller, &is_focus_out);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
- (void)applicationWillTerminate:(UIApplication *)application {
|
- (void)applicationWillTerminate:(UIApplication *)application {
|
||||||
[self deinitGameControllers];
|
[self deinitGameControllers];
|
||||||
|
|
||||||
|
@ -656,14 +712,7 @@ static int frame_count = 0;
|
||||||
- (void)applicationDidEnterBackground:(UIApplication *)application {
|
- (void)applicationDidEnterBackground:(UIApplication *)application {
|
||||||
///@TODO maybe add pause motionManager? and where would we unpause it?
|
///@TODO maybe add pause motionManager? and where would we unpause it?
|
||||||
|
|
||||||
if (OS::get_singleton()->get_main_loop())
|
on_focus_out(view_controller, &is_focus_out);
|
||||||
OS::get_singleton()->get_main_loop()->notification(
|
|
||||||
MainLoop::NOTIFICATION_WM_FOCUS_OUT);
|
|
||||||
|
|
||||||
[view_controller.view stopAnimation];
|
|
||||||
if (OS::get_singleton()->native_video_is_playing()) {
|
|
||||||
OSIPhone::get_singleton()->native_video_focus_out();
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)applicationWillEnterForeground:(UIApplication *)application {
|
- (void)applicationWillEnterForeground:(UIApplication *)application {
|
||||||
|
@ -678,19 +727,7 @@ static int frame_count = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)applicationDidBecomeActive:(UIApplication *)application {
|
- (void)applicationDidBecomeActive:(UIApplication *)application {
|
||||||
if (OS::get_singleton()->get_main_loop())
|
on_focus_in(view_controller, &is_focus_out);
|
||||||
OS::get_singleton()->get_main_loop()->notification(
|
|
||||||
MainLoop::NOTIFICATION_WM_FOCUS_IN);
|
|
||||||
|
|
||||||
[view_controller.view
|
|
||||||
startAnimation]; // FIXME: resume seems to be recommended elsewhere
|
|
||||||
if (OSIPhone::get_singleton()->native_video_is_playing()) {
|
|
||||||
OSIPhone::get_singleton()->native_video_unpause();
|
|
||||||
};
|
|
||||||
|
|
||||||
// Fixed audio can not resume if it is interrupted cause by an incoming phone call
|
|
||||||
if (AudioDriverCoreAudio::get_singleton() != NULL)
|
|
||||||
AudioDriverCoreAudio::get_singleton()->start();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)dealloc {
|
- (void)dealloc {
|
||||||
|
|
Loading…
Reference in New Issue