273273static int open_capture_devices = 0 ;
274274
275275#if !MACOSX_COREAUDIO
276- static BOOL update_audio_ session ()
276+
277+ static void interruption_begin (_THIS)
278+ {
279+ if (this != NULL && this->hidden ->audioQueue != NULL ) {
280+ this->hidden ->interrupted = SDL_TRUE;
281+ AudioQueuePause (this->hidden ->audioQueue );
282+ }
283+ }
284+
285+ static void interruption_end (_THIS)
286+ {
287+ if (this != NULL && this->hidden != NULL && this->hidden ->audioQueue != NULL
288+ && this->hidden ->interrupted ) {
289+ this->hidden ->interrupted = SDL_FALSE;
290+ AudioQueueStart (this->hidden ->audioQueue , NULL );
291+ }
292+ }
293+
294+ @interface SDLInterruptionListener : NSObject
295+
296+ @property (nonatomic , assign ) SDL_AudioDevice *device;
297+
298+ @end
299+
300+ @implementation SDLInterruptionListener
301+
302+ - (void )audioSessionInterruption : (NSNotification *)note
303+ {
304+ @synchronized (self) {
305+ NSNumber *type = note.userInfo [AVAudioSessionInterruptionTypeKey];
306+ if (type.unsignedIntegerValue == AVAudioSessionInterruptionTypeBegan) {
307+ interruption_begin (self.device );
308+ } else {
309+ interruption_end (self.device );
310+ }
311+ }
312+ }
313+
314+ - (void )applicationBecameActive : (NSNotification *)note
315+ {
316+ @synchronized (self) {
317+ interruption_end (self.device );
318+ }
319+ }
320+
321+ @end
322+
323+ static BOOL update_audio_session (_THIS, SDL_bool open)
277324{
278325 @autoreleasepool {
279326 AVAudioSession *session = [AVAudioSession sharedInstance ];
327+ NSNotificationCenter *center = [NSNotificationCenter defaultCenter ];
280328 NSString *category;
281329 NSError *err = nil ;
282330
@@ -291,6 +339,12 @@ static BOOL update_audio_session()
291339 category = AVAudioSessionCategoryAmbient;
292340 }
293341
342+ if (![session setCategory: category error: &err]) {
343+ NSString *desc = err.description ;
344+ SDL_SetError (" Could not set Audio Session category: %s " , desc.UTF8String );
345+ return NO ;
346+ }
347+
294348 if (open_playback_devices + open_capture_devices == 1 ) {
295349 if (![session setActive: YES error: &err]) {
296350 NSString *desc = err.description ;
@@ -301,10 +355,38 @@ static BOOL update_audio_session()
301355 [session setActive: NO error: nil ];
302356 }
303357
304- if (! [session setCategory :category error :& err ]) {
305- NSString * desc = err .description ;
306- SDL_ SetError ("Could not set Audio Session category: %s" , desc .UTF8String );
307- return NO ;
358+ if (open) {
359+ SDLInterruptionListener *listener = [SDLInterruptionListener new ];
360+ listener.device = this;
361+
362+ [center addObserver: listener
363+ selector: @selector (audioSessionInterruption: )
364+ name: AVAudioSessionInterruptionNotification
365+ object: session];
366+
367+ /* An interruption end notification is not guaranteed to be sent if
368+ we were previously interrupted... resuming if needed when the app
369+ becomes active seems to be the way to go. */
370+ [center addObserver: listener
371+ selector: @selector (applicationBecameActive: )
372+ name: UIApplicationDidBecomeActiveNotification
373+ object: session];
374+
375+ [center addObserver: listener
376+ selector: @selector (applicationBecameActive: )
377+ name: UIApplicationWillEnterForegroundNotification
378+ object: session];
379+
380+ this->hidden ->interruption_listener = CFBridgingRetain (listener);
381+ } else {
382+ if (this->hidden ->interruption_listener != NULL ) {
383+ SDLInterruptionListener *listener = nil ;
384+ listener = (SDLInterruptionListener *) CFBridgingRelease (this->hidden ->interruption_listener );
385+ @synchronized (listener) {
386+ listener.device = NULL ;
387+ }
388+ [center removeObserver: listener];
389+ }
308390 }
309391 }
310392
@@ -441,6 +523,10 @@ static BOOL update_audio_session()
441523 AudioObjectRemovePropertyListener (this->hidden ->deviceID , &alive_address, device_unplugged, this);
442524#endif
443525
526+ #if !MACOSX_COREAUDIO
527+ update_audio_session (this, SDL_FALSE);
528+ #endif
529+
444530 if (this->hidden ->thread ) {
445531 SDL_AtomicSet (&this->hidden ->shutdown , 1 );
446532 SDL_WaitThread (this->hidden ->thread , NULL );
@@ -468,10 +554,6 @@ static BOOL update_audio_session()
468554 } else {
469555 open_playback_devices--;
470556 }
471-
472- # if ! MACOSX_ COREAUDIO
473- update_audio_ session ();
474- # endif
475557}
476558
477559#if MACOSX_COREAUDIO
@@ -649,7 +731,7 @@ static BOOL update_audio_session()
649731 }
650732
651733#if !MACOSX_COREAUDIO
652- if (! update_audio_ session ()) {
734+ if (!update_audio_session (this, SDL_TRUE )) {
653735 return -1 ;
654736 }
655737#endif
0 commit comments