Allow background music to play in the "play and record" case on iOS
authorSam Lantinga <slouken@libsdl.org>
Thu, 26 Mar 2020 19:30:17 -0700
changeset 136769c0592cc3e92
parent 13675 e3844f61860a
child 13677 498a7f27758e
Allow background music to play in the "play and record" case on iOS
src/audio/coreaudio/SDL_coreaudio.m
     1.1 --- a/src/audio/coreaudio/SDL_coreaudio.m	Thu Mar 26 20:28:04 2020 -0400
     1.2 +++ b/src/audio/coreaudio/SDL_coreaudio.m	Thu Mar 26 19:30:17 2020 -0700
     1.3 @@ -327,44 +327,54 @@
     1.4          AVAudioSession *session = [AVAudioSession sharedInstance];
     1.5          NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
     1.6  
     1.7 -        /* Set category to ambient by default so that other music continues playing. */
     1.8 -        NSString *category = AVAudioSessionCategoryAmbient;
     1.9 +        NSString *category = AVAudioSessionCategoryPlayback;
    1.10          NSString *mode = AVAudioSessionModeDefault;
    1.11 -        NSUInteger options = 0;
    1.12 +        NSUInteger options = AVAudioSessionCategoryOptionMixWithOthers;
    1.13          NSError *err = nil;
    1.14 +        const char *hint;
    1.15  
    1.16 -        if (open_playback_devices && open_capture_devices) {
    1.17 +        hint = SDL_GetHint(SDL_HINT_AUDIO_CATEGORY);
    1.18 +        if (hint) {
    1.19 +            if (SDL_strcasecmp(hint, "AVAudioSessionCategoryAmbient") == 0) {
    1.20 +                category = AVAudioSessionCategoryAmbient;
    1.21 +            } else if (SDL_strcasecmp(hint, "AVAudioSessionCategorySoloAmbient") == 0) {
    1.22 +                category = AVAudioSessionCategorySoloAmbient;
    1.23 +                options &= ~AVAudioSessionCategoryOptionMixWithOthers;
    1.24 +            } else if (SDL_strcasecmp(hint, "AVAudioSessionCategoryPlayback") == 0 ||
    1.25 +                       SDL_strcasecmp(hint, "playback") == 0) {
    1.26 +                category = AVAudioSessionCategoryPlayback;
    1.27 +                options &= ~AVAudioSessionCategoryOptionMixWithOthers;
    1.28 +            } else if (SDL_strcasecmp(hint, "AVAudioSessionCategoryPlayAndRecord") == 0 ||
    1.29 +                       SDL_strcasecmp(hint, "playandrecord") == 0) {
    1.30 +                category = AVAudioSessionCategoryPlayAndRecord;
    1.31 +            }
    1.32 +        } else if (open_playback_devices && open_capture_devices) {
    1.33              category = AVAudioSessionCategoryPlayAndRecord;
    1.34 -#if !TARGET_OS_TV
    1.35 -            options = AVAudioSessionCategoryOptionDefaultToSpeaker;
    1.36 -#endif
    1.37          } else if (open_capture_devices) {
    1.38              category = AVAudioSessionCategoryRecord;
    1.39 -        } else {
    1.40 -            const char *hint = SDL_GetHint(SDL_HINT_AUDIO_CATEGORY);
    1.41 -            if (hint) {
    1.42 -                if (SDL_strcasecmp(hint, "AVAudioSessionCategoryAmbient") == 0) {
    1.43 -                    category = AVAudioSessionCategoryAmbient;
    1.44 -                } else if (SDL_strcasecmp(hint, "AVAudioSessionCategorySoloAmbient") == 0) {
    1.45 -                    category = AVAudioSessionCategorySoloAmbient;
    1.46 -                } else if (SDL_strcasecmp(hint, "AVAudioSessionCategoryPlayback") == 0 ||
    1.47 -                           SDL_strcasecmp(hint, "playback") == 0) {
    1.48 -                    category = AVAudioSessionCategoryPlayback;
    1.49 +        }
    1.50 +
    1.51 +#if !TARGET_OS_TV
    1.52 +        if (category == AVAudioSessionCategoryPlayAndRecord) {
    1.53 +            options |= AVAudioSessionCategoryOptionDefaultToSpeaker;
    1.54 +        }
    1.55 +#endif
    1.56 +
    1.57 +        if ([session respondsToSelector:@selector(setCategory:mode:options:error:)]) {
    1.58 +            if (![session.category isEqualToString:category] || session.categoryOptions != options) {
    1.59 +                if (![session setCategory:category mode:mode options:options error:&err]) {
    1.60 +                    NSString *desc = err.description;
    1.61 +                    SDL_SetError("Could not set Audio Session category: %s", desc.UTF8String);
    1.62 +                    return NO;
    1.63                  }
    1.64              }
    1.65 -        }
    1.66 -
    1.67 -        if ([session respondsToSelector:@selector(setCategory:mode:options:error:)]) {
    1.68 -            if (![session setCategory:category mode:mode options:options error:&err]) {
    1.69 -                NSString *desc = err.description;
    1.70 -                SDL_SetError("Could not set Audio Session category: %s", desc.UTF8String);
    1.71 -                return NO;
    1.72 -            }
    1.73          } else {
    1.74 -            if (![session setCategory:category error:&err]) {
    1.75 -                NSString *desc = err.description;
    1.76 -                SDL_SetError("Could not set Audio Session category: %s", desc.UTF8String);
    1.77 -                return NO;
    1.78 +            if (![session.category isEqualToString:category]) {
    1.79 +                if (![session setCategory:category error:&err]) {
    1.80 +                    NSString *desc = err.description;
    1.81 +                    SDL_SetError("Could not set Audio Session category: %s", desc.UTF8String);
    1.82 +                    return NO;
    1.83 +                }
    1.84              }
    1.85          }
    1.86  
    1.87 @@ -864,7 +874,7 @@
    1.88              this->spec.channels = session.preferredOutputNumberOfChannels;
    1.89          }
    1.90  #else
    1.91 -		/* Calling setPreferredOutputNumberOfChannels seems to break audio output on iOS */
    1.92 +        /* Calling setPreferredOutputNumberOfChannels seems to break audio output on iOS */
    1.93  #endif /* TARGET_OS_TV */
    1.94      }
    1.95  #endif