diff options
| author | Andre Weissflog <floooh@gmail.com> | 2021-02-16 20:29:19 +0100 |
|---|---|---|
| committer | Andre Weissflog <floooh@gmail.com> | 2021-02-16 20:30:31 +0100 |
| commit | 83bf2da8fd24be7b6d9b0f3aaa52f901c922de64 (patch) | |
| tree | e3a938b50ddeffef67fd91bfb1a840456400859e | |
| parent | 8c2c4a891ea855d7259047eb195f1e041928e8d7 (diff) | |
sokol_audio.h: fix ARC vs non-ARC on iOS
| -rw-r--r-- | sokol_audio.h | 64 |
1 files changed, 36 insertions, 28 deletions
diff --git a/sokol_audio.h b/sokol_audio.h index f85f3d67..83d27e1d 100644 --- a/sokol_audio.h +++ b/sokol_audio.h @@ -41,7 +41,8 @@ - Windows: WASAPI - Linux: ALSA (link with asound) - - macOS/iOS: CoreAudio (link with AudioToolbox) + - macOS: CoreAudio (link with AudioToolbox) + - iOS: CoreAudio+AVAudioSession (link with AudioToolbox and AVFramework) - emscripten: WebAudio with ScriptProcessorNode - Android: OpenSLES (link with OpenSLES) @@ -309,6 +310,7 @@ The CoreAudio backend is selected on macOS and iOS (__APPLE__ is defined). Since the CoreAudio API is implemented in C (not Objective-C) on macOS the implementation part of Sokol Audio can be included into a C source file. + However on iOS, Sokol Audio must be compiled as Objective-C due to it's reliance on the AVAudioSession object. @@ -513,9 +515,14 @@ inline void saudio_setup(const saudio_desc& desc) { return saudio_setup(&desc); #elif defined(__APPLE__) #include <TargetConditionals.h> #include <AudioToolbox/AudioToolbox.h> -#if TARGET_OS_IOS - #include <AVFoundation/AVFoundation.h> -#endif + #if TARGET_OS_IOS + #if !defined(__cplusplus) + #if __has_feature(objc_arc) && !__has_feature(objc_arc_fields) + #error "sokol_audio.h on iOS requires __has_feature(objc_arc_field) if ARC is enabled (use a more recent compiler version)" + #endif + #endif + #include <AVFoundation/AVFoundation.h> + #endif #elif (defined(__linux__) || defined(__unix__)) && !defined(__EMSCRIPTEN__) && !defined(__ANDROID__) #define ALSA_PCM_NEW_HW_PARAMS_API #include <alsa/asoundlib.h> @@ -603,9 +610,9 @@ typedef struct { typedef struct { AudioQueueRef ca_audio_queue; -#if TARGET_OS_IOS - void* ca_interruption_handler; -#endif + #if TARGET_OS_IOS + id ca_interruption_handler; + #endif } _saudio_backend_t; /*=== ALSA BACKEND DECLARATIONS ==============================================*/ @@ -982,31 +989,33 @@ _SOKOL_PRIVATE void _saudio_backend_shutdown(void) { }; #elif defined(__APPLE__) #if TARGET_OS_IOS -@interface _saudio_interruption_handler:NSObject { -} +#if __has_feature(objc_arc) +#define _SAUDIO_OBJC_RELEASE(obj) { obj = nil; } +#else +#define _SAUDIO_OBJC_RELEASE(obj) { [obj release]; obj = nil; } +#endif + +@interface _saudio_interruption_handler : NSObject { } @end @implementation _saudio_interruption_handler --(id)init -{ +-(id)init { self = [super init]; AVAudioSession* session = [AVAudioSession sharedInstance]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handle_interruption:) name:AVAudioSessionInterruptionNotification object:session]; return self; } --(void)dealloc -{ +-(void)dealloc { [self remove_handler]; + [super dealloc]; } --(void)remove_handler -{ +-(void)remove_handler { [[NSNotificationCenter defaultCenter] removeObserver:self name:@"AVAudioSessionInterruptionNotification" object:nil]; } --(void)handle_interruption:(NSNotification*)notification -{ +-(void)handle_interruption:(NSNotification*)notification { AVAudioSession* session = [AVAudioSession sharedInstance]; SOKOL_ASSERT(session); NSDictionary* dict = notification.userInfo; @@ -1050,16 +1059,17 @@ _SOKOL_PRIVATE void _saudio_coreaudio_callback(void* user_data, AudioQueueRef qu _SOKOL_PRIVATE bool _saudio_backend_init(void) { SOKOL_ASSERT(0 == _saudio.backend.ca_audio_queue); -#if TARGET_OS_IOS + #if TARGET_OS_IOS /* activate audio session */ AVAudioSession* session = [AVAudioSession sharedInstance]; - SOKOL_ASSERT(session); + SOKOL_ASSERT(session != nil); [session setCategory: AVAudioSessionCategoryPlayback withOptions:AVAudioSessionCategoryOptionDefaultToSpeaker error:nil]; [session setActive:true error:nil]; /* create interruption handler */ - _saudio.backend.ca_interruption_handler = (__bridge_retained void*)[[_saudio_interruption_handler alloc] init]; -#endif + _saudio.backend.ca_interruption_handler = [[_saudio_interruption_handler alloc] init]; + #endif + /* create an audio queue with fp32 samples */ AudioStreamBasicDescription fmt; memset(&fmt, 0, sizeof(fmt)); @@ -1099,19 +1109,17 @@ _SOKOL_PRIVATE void _saudio_backend_shutdown(void) { AudioQueueStop(_saudio.backend.ca_audio_queue, true); AudioQueueDispose(_saudio.backend.ca_audio_queue, false); _saudio.backend.ca_audio_queue = NULL; -#if TARGET_OS_IOS + #if TARGET_OS_IOS /* remove interruption handler */ - if (_saudio.backend.ca_interruption_handler != NULL) { - _saudio_interruption_handler* interruption_handler = (__bridge_transfer _saudio_interruption_handler*)_saudio.backend.ca_interruption_handler; - [interruption_handler remove_handler]; - _saudio.backend.ca_interruption_handler = NULL; + if (_saudio.backend.ca_interruption_handler != nil) { + [_saudio.backend.ca_interruption_handler remove_handler]; + _SAUDIO_OBJC_RELEASE(_saudio.backend.ca_interruption_handler); } - /* deactivate audio session */ AVAudioSession* session = [AVAudioSession sharedInstance]; SOKOL_ASSERT(session); [session setActive:false error:nil];; -#endif + #endif } /*=== ALSA BACKEND IMPLEMENTATION ============================================*/ |