Skip to content

Commit a74722e

Browse files
committed
coreaudio: Always init/deinit session listener on iOS.
Previously, if UpdateAudioSession() failed on close--which it might if something strange has happened with the system's audio configuration--the listener wouldn't be deregistered, and would risk touching a free'd pointer if the app moved to or from the background afterwards, firing an event handler that should have been deregistered. Closes #15439.
1 parent 0bf2fa8 commit a74722e

1 file changed

Lines changed: 37 additions & 33 deletions

File tree

src/audio/coreaudio/SDL_coreaudio.m

Lines changed: 37 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -502,39 +502,6 @@ static bool UpdateAudioSession(SDL_AudioDevice *device, bool open, bool allow_pl
502502
[session setActive:NO error:nil];
503503
session_active = false;
504504
}
505-
506-
if (open) {
507-
SDLInterruptionListener *listener = [SDLInterruptionListener new];
508-
listener.device = device;
509-
510-
[center addObserver:listener
511-
selector:@selector(audioSessionInterruption:)
512-
name:AVAudioSessionInterruptionNotification
513-
object:session];
514-
515-
/* An interruption end notification is not guaranteed to be sent if
516-
we were previously interrupted... resuming if needed when the app
517-
becomes active seems to be the way to go. */
518-
// Note: object: below needs to be nil, as otherwise it filters by the object, and session doesn't send foreground / active notifications.
519-
[center addObserver:listener
520-
selector:@selector(applicationBecameActive:)
521-
name:UIApplicationDidBecomeActiveNotification
522-
object:nil];
523-
524-
[center addObserver:listener
525-
selector:@selector(applicationBecameActive:)
526-
name:UIApplicationWillEnterForegroundNotification
527-
object:nil];
528-
529-
device->hidden->interruption_listener = CFBridgingRetain(listener);
530-
} else {
531-
SDLInterruptionListener *listener = nil;
532-
listener = (SDLInterruptionListener *)CFBridgingRelease(device->hidden->interruption_listener);
533-
[center removeObserver:listener];
534-
@synchronized(listener) {
535-
listener.device = NULL;
536-
}
537-
}
538505
}
539506

540507
return true;
@@ -627,6 +594,17 @@ static void COREAUDIO_CloseDevice(SDL_AudioDevice *device)
627594
return;
628595
}
629596

597+
#ifndef MACOSX_COREAUDIO
598+
if (device->hidden->interruption_listener) {
599+
SDLInterruptionListener *listener = (SDLInterruptionListener *)CFBridgingRelease(device->hidden->interruption_listener);
600+
device->hidden->interruption_listener = nil;
601+
[center removeObserver:listener];
602+
@synchronized(listener) {
603+
listener.device = NULL;
604+
}
605+
}
606+
#endif
607+
630608
// dispose of the audio queue before waiting on the thread, or it might stall for a long time!
631609
if (device->hidden->audioQueue) {
632610
AudioQueueFlush(device->hidden->audioQueue);
@@ -998,6 +976,32 @@ static bool COREAUDIO_OpenDevice(SDL_AudioDevice *device)
998976
return SDL_SetError("%s", device->hidden->thread_error);
999977
}
1000978

979+
#ifndef MACOSX_COREAUDIO
980+
SDLInterruptionListener *listener = [SDLInterruptionListener new];
981+
listener.device = device;
982+
983+
[center addObserver:listener
984+
selector:@selector(audioSessionInterruption:)
985+
name:AVAudioSessionInterruptionNotification
986+
object:session];
987+
988+
/* An interruption end notification is not guaranteed to be sent if
989+
we were previously interrupted... resuming if needed when the app
990+
becomes active seems to be the way to go. */
991+
// Note: object: below needs to be nil, as otherwise it filters by the object, and session doesn't send foreground / active notifications.
992+
[center addObserver:listener
993+
selector:@selector(applicationBecameActive:)
994+
name:UIApplicationDidBecomeActiveNotification
995+
object:nil];
996+
997+
[center addObserver:listener
998+
selector:@selector(applicationBecameActive:)
999+
name:UIApplicationWillEnterForegroundNotification
1000+
object:nil];
1001+
1002+
device->hidden->interruption_listener = CFBridgingRetain(listener);
1003+
#endif
1004+
10011005
return (device->hidden->thread != NULL);
10021006
}
10031007

0 commit comments

Comments
 (0)