diff options
author | Ruslan Mustakov <r.mustakov@gmail.com> | 2018-05-07 15:44:07 +0700 |
---|---|---|
committer | Ruslan Mustakov <r.mustakov@gmail.com> | 2018-05-07 15:48:46 +0700 |
commit | 96301e934d7600975922c5f373a488a532d77aad (patch) | |
tree | 7a521d7a508e2e872944ef691df45771f1735318 | |
parent | e15305721da0e4478b62efcda3e79f1c04e7a901 (diff) |
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.
-rw-r--r-- | drivers/coreaudio/audio_driver_coreaudio.cpp | 13 | ||||
-rw-r--r-- | drivers/coreaudio/audio_driver_coreaudio.h | 1 | ||||
-rw-r--r-- | platform/iphone/app_delegate.h | 1 | ||||
-rw-r--r-- | platform/iphone/app_delegate.mm | 79 |
4 files changed, 72 insertions, 22 deletions
diff --git a/drivers/coreaudio/audio_driver_coreaudio.cpp b/drivers/coreaudio/audio_driver_coreaudio.cpp index c84469f26f..6e451eabcd 100644 --- a/drivers/coreaudio/audio_driver_coreaudio.cpp +++ b/drivers/coreaudio/audio_driver_coreaudio.cpp @@ -217,13 +217,24 @@ void AudioDriverCoreAudio::start() { if (!active) { OSStatus result = AudioOutputUnitStart(audio_unit); if (result != noErr) { - ERR_PRINT("AudioOutputUnitStart failed"); + ERR_PRINT(("AudioOutputUnitStart failed, code: " + itos(result)).utf8().get_data()); } else { 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 { return mix_rate; }; diff --git a/drivers/coreaudio/audio_driver_coreaudio.h b/drivers/coreaudio/audio_driver_coreaudio.h index 9891920263..c44e225521 100644 --- a/drivers/coreaudio/audio_driver_coreaudio.h +++ b/drivers/coreaudio/audio_driver_coreaudio.h @@ -90,6 +90,7 @@ public: virtual void finish(); bool try_lock(); + void stop(); AudioDriverCoreAudio(); ~AudioDriverCoreAudio(); diff --git a/platform/iphone/app_delegate.h b/platform/iphone/app_delegate.h index f14864b5b7..c34b5053d6 100644 --- a/platform/iphone/app_delegate.h +++ b/platform/iphone/app_delegate.h @@ -37,6 +37,7 @@ @interface AppDelegate : NSObject <UIApplicationDelegate, GLViewDelegate> { //@property (strong, nonatomic) UIWindow *window; ViewController *view_controller; + bool is_focus_out; }; @property(strong, nonatomic) UIWindow *window; diff --git a/platform/iphone/app_delegate.mm b/platform/iphone/app_delegate.mm index 9e6bbff1d7..7ed1328b20 100644 --- a/platform/iphone/app_delegate.mm +++ b/platform/iphone/app_delegate.mm @@ -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 { // create our dictionary if we don't have one yet if (ios_joysticks == nil) { @@ -569,6 +605,8 @@ static int frame_count = 0; - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { CGRect rect = [[UIScreen mainScreen] bounds]; + is_focus_out = false; + [application setStatusBarHidden:YES withAnimation:UIStatusBarAnimationNone]; // disable idle timer // application.idleTimerDisabled = YES; @@ -628,6 +666,12 @@ static int frame_count = 0; [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_height = rect.size.height - rect.origin.y; @@ -639,6 +683,18 @@ static int frame_count = 0; 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 { [self deinitGameControllers]; @@ -656,14 +712,7 @@ static int frame_count = 0; - (void)applicationDidEnterBackground:(UIApplication *)application { ///@TODO maybe add pause motionManager? and where would we unpause it? - 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(); - }; + on_focus_out(view_controller, &is_focus_out); } - (void)applicationWillEnterForeground:(UIApplication *)application { @@ -678,19 +727,7 @@ static int frame_count = 0; } - (void)applicationDidBecomeActive:(UIApplication *)application { - if (OS::get_singleton()->get_main_loop()) - 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(); + on_focus_in(view_controller, &is_focus_out); } - (void)dealloc { |