Commit 4e7d501e authored by David Reid's avatar David Reid

Merge branch 'dev' of https://github.com/dr-soft/miniaudio into dev

parents 1c998a57 ac995ee7
...@@ -1880,6 +1880,31 @@ typedef enum ...@@ -1880,6 +1880,31 @@ typedef enum
ma_share_mode_exclusive ma_share_mode_exclusive
} ma_share_mode; } ma_share_mode;
/* iOS/tvOS/watchOS session categories. */
typedef enum
{
ma_ios_session_category_default = 0, /* AVAudioSessionCategoryPlayAndRecord with AVAudioSessionCategoryOptionDefaultToSpeaker. */
ma_ios_session_category_none, /* Leave the session category unchanged. */
ma_ios_session_category_ambient, /* AVAudioSessionCategoryAmbient */
ma_ios_session_category_solo_ambient, /* AVAudioSessionCategorySoloAmbient */
ma_ios_session_category_playback, /* AVAudioSessionCategoryPlayback */
ma_ios_session_category_record, /* AVAudioSessionCategoryRecord */
ma_ios_session_category_play_and_record, /* AVAudioSessionCategoryPlayAndRecord */
ma_ios_session_category_multi_route /* AVAudioSessionCategoryMultiRoute */
} ma_ios_session_category;
/* iOS/tvOS/watchOS session category options */
typedef enum
{
ma_ios_session_category_option_mix_with_others = 0x01, /* AVAudioSessionCategoryOptionMixWithOthers */
ma_ios_session_category_option_duck_others = 0x02, /* AVAudioSessionCategoryOptionDuckOthers */
ma_ios_session_category_option_allow_bluetooth = 0x04, /* AVAudioSessionCategoryOptionAllowBluetooth */
ma_ios_session_category_option_default_to_speaker = 0x08, /* AVAudioSessionCategoryOptionDefaultToSpeaker */
ma_ios_session_category_option_interrupt_spoken_audio_and_mix_with_others = 0x11, /* AVAudioSessionCategoryOptionInterruptSpokenAudioAndMixWithOthers */
ma_ios_session_category_option_allow_bluetooth_a2dp = 0x20, /* AVAudioSessionCategoryOptionAllowBluetoothA2DP */
ma_ios_session_category_option_allow_air_play = 0x40, /* AVAudioSessionCategoryOptionAllowAirPlay */
} ma_ios_session_category_option;
typedef union typedef union
{ {
#ifdef MA_SUPPORT_WASAPI #ifdef MA_SUPPORT_WASAPI
...@@ -2018,7 +2043,8 @@ typedef struct ...@@ -2018,7 +2043,8 @@ typedef struct
} pulse; } pulse;
struct struct
{ {
ma_bool32 noBluetoothRouting; ma_ios_session_category sessionCategory;
ma_uint32 sessionCategoryOptions;
} coreaudio; } coreaudio;
struct struct
{ {
...@@ -5244,9 +5270,14 @@ ma_result ma_semaphore_init__posix(ma_context* pContext, int initialValue, ma_se ...@@ -5244,9 +5270,14 @@ ma_result ma_semaphore_init__posix(ma_context* pContext, int initialValue, ma_se
{ {
(void)pContext; (void)pContext;
#if defined(MA_APPLE)
/* Not yet implemented for Apple platforms since sem_init() is deprecated. Need to use a named semaphore via sem_open() instead. */
return MA_INVALID_OPERATION;
#else
if (sem_init(&pSemaphore->posix.semaphore, 0, (unsigned int)initialValue) == 0) { if (sem_init(&pSemaphore->posix.semaphore, 0, (unsigned int)initialValue) == 0) {
return MA_FAILED_TO_CREATE_SEMAPHORE; return MA_FAILED_TO_CREATE_SEMAPHORE;
} }
#endif
return MA_SUCCESS; return MA_SUCCESS;
} }
...@@ -17933,6 +17964,12 @@ Core Audio Backend ...@@ -17933,6 +17964,12 @@ Core Audio Backend
#if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE == 1 #if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE == 1
#define MA_APPLE_MOBILE #define MA_APPLE_MOBILE
#if defined(TARGET_OS_TV) && TARGET_OS_TV == 1
#define MA_APPLE_TV
#endif
#if defined(TARGET_OS_WATCH) && TARGET_OS_WATCH == 1
#define MA_APPLE_WATCH
#endif
#else #else
#define MA_APPLE_DESKTOP #define MA_APPLE_DESKTOP
#endif #endif
...@@ -20053,10 +20090,10 @@ ma_result ma_device_init_internal__coreaudio(ma_context* pContext, ma_device_typ ...@@ -20053,10 +20090,10 @@ ma_result ma_device_init_internal__coreaudio(ma_context* pContext, ma_device_typ
AVAudioSession outputNumberOfChannels. I'm going to try using the AVAudioSession values instead. AVAudioSession outputNumberOfChannels. I'm going to try using the AVAudioSession values instead.
*/ */
if (deviceType == ma_device_type_playback) { if (deviceType == ma_device_type_playback) {
bestFormat.mChannelsPerFrame = pAudioSession.outputNumberOfChannels; bestFormat.mChannelsPerFrame = (UInt32)pAudioSession.outputNumberOfChannels;
} }
if (deviceType == ma_device_type_capture) { if (deviceType == ma_device_type_capture) {
bestFormat.mChannelsPerFrame = pAudioSession.inputNumberOfChannels; bestFormat.mChannelsPerFrame = (UInt32)pAudioSession.inputNumberOfChannels;
} }
} }
...@@ -20564,35 +20601,61 @@ ma_result ma_context_uninit__coreaudio(ma_context* pContext) ...@@ -20564,35 +20601,61 @@ ma_result ma_context_uninit__coreaudio(ma_context* pContext)
return MA_SUCCESS; return MA_SUCCESS;
} }
static AVAudioSessionCategory ma_to_AVAudioSessionCategory(ma_ios_session_category category)
{
/* The "default" and "none" categories are treated different and should not be used as an input into this function. */
ma_assert(category != ma_ios_session_category_default);
ma_assert(category != ma_ios_session_category_none);
switch (category) {
case ma_ios_session_category_ambient: return AVAudioSessionCategoryAmbient;
case ma_ios_session_category_solo_ambient: return AVAudioSessionCategorySoloAmbient;
case ma_ios_session_category_playback: return AVAudioSessionCategoryPlayback;
case ma_ios_session_category_record: return AVAudioSessionCategoryRecord;
case ma_ios_session_category_play_and_record: return AVAudioSessionCategoryPlayAndRecord;
case ma_ios_session_category_multi_route: return AVAudioSessionCategoryMultiRoute;
case ma_ios_session_category_none: return AVAudioSessionCategoryAmbient;
case ma_ios_session_category_default: return AVAudioSessionCategoryAmbient;
default: return AVAudioSessionCategoryAmbient;
}
}
ma_result ma_context_init__coreaudio(const ma_context_config* pConfig, ma_context* pContext) ma_result ma_context_init__coreaudio(const ma_context_config* pConfig, ma_context* pContext)
{ {
ma_assert(pConfig != NULL);
ma_assert(pContext != NULL); ma_assert(pContext != NULL);
(void)pConfig;
#if defined(MA_APPLE_MOBILE) #if defined(MA_APPLE_MOBILE)
@autoreleasepool { @autoreleasepool {
AVAudioSession* pAudioSession = [AVAudioSession sharedInstance]; AVAudioSession* pAudioSession = [AVAudioSession sharedInstance];
AVAudioSessionCategoryOptions options = 0; AVAudioSessionCategoryOptions options = pConfig->coreaudio.sessionCategoryOptions;
ma_assert(pAudioSession != NULL); ma_assert(pAudioSession != NULL);
/* if (pConfig->coreaudio.sessionCategory == ma_ios_session_category_default) {
Try enabling routing to Bluetooth devices. The AVAudioSessionCategoryOptionAllowBluetoothA2DP is only available /*
starting from iOS 10 so I'm doing a version check before enabling this. I'm going to use trial and error to determine our default session category. First we'll try PlayAndRecord. If that fails
*/ we'll try Playback and if that fails we'll try record. If all of these fail we'll just not set the category.
if (!pConfig->coreaudio.noBluetoothRouting) { */
if ([[[UIDevice currentDevice] systemVersion] compare:@"10.0" options:NSNumericSearch] != NSOrderedAscending) { #if !defined(MA_APPLE_TV) && !defined(MA_APPLE_WATCH)
options = 0x20; /* 0x20 = AVAudioSessionCategoryOptionAllowBluetoothA2DP */ options |= AVAudioSessionCategoryOptionDefaultToSpeaker;
} #endif
}
[pAudioSession setCategory: AVAudioSessionCategoryPlayAndRecord withOptions:options error:nil]; if ([pAudioSession setCategory: AVAudioSessionCategoryPlayAndRecord withOptions:options error:nil]) {
/* Using PlayAndRecord */
/* By default we want miniaudio to use the speakers instead of the receiver. In the future this may be customizable. */ } else if ([pAudioSession setCategory: AVAudioSessionCategoryPlayback withOptions:options error:nil]) {
ma_bool32 useSpeakers = MA_TRUE; /* Using Playback */
if (useSpeakers) { } else if ([pAudioSession setCategory: AVAudioSessionCategoryRecord withOptions:options error:nil]) {
[pAudioSession overrideOutputAudioPort:AVAudioSessionPortOverrideSpeaker error:nil]; /* Using Record */
} else {
/* Leave as default? */
}
} else {
if (pConfig->coreaudio.sessionCategory != ma_ios_session_category_none) {
if (![pAudioSession setCategory: ma_to_AVAudioSessionCategory(pConfig->coreaudio.sessionCategory) withOptions:options error:nil]) {
return MA_INVALID_OPERATION; /* Failed to set session category. */
}
}
} }
} }
#endif #endif
...@@ -20603,8 +20666,8 @@ ma_result ma_context_init__coreaudio(const ma_context_config* pConfig, ma_contex ...@@ -20603,8 +20666,8 @@ ma_result ma_context_init__coreaudio(const ma_context_config* pConfig, ma_contex
return MA_API_NOT_FOUND; return MA_API_NOT_FOUND;
} }
pContext->coreaudio.CFStringGetCString = ma_dlsym(pContext, pContext->coreaudio.hCoreFoundation, "CFStringGetCString"); pContext->coreaudio.CFStringGetCString = ma_dlsym(pContext, pContext->coreaudio.hCoreFoundation, "CFStringGetCString");
pContext->coreaudio.CFRelease = ma_dlsym(pContext, pContext->coreaudio.hCoreFoundation, "CFRelease"); pContext->coreaudio.CFRelease = ma_dlsym(pContext, pContext->coreaudio.hCoreFoundation, "CFRelease");
pContext->coreaudio.hCoreAudio = ma_dlopen(pContext, "CoreAudio.framework/CoreAudio"); pContext->coreaudio.hCoreAudio = ma_dlopen(pContext, "CoreAudio.framework/CoreAudio");
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment