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.
This commit is contained in:
parent
e15305721d
commit
96301e934d
4 changed files with 72 additions and 22 deletions
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -90,6 +90,7 @@ public:
|
|||
virtual void finish();
|
||||
|
||||
bool try_lock();
|
||||
void stop();
|
||||
|
||||
AudioDriverCoreAudio();
|
||||
~AudioDriverCoreAudio();
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 {
|
||||
|
|
Loading…
Reference in a new issue