mirror of
https://github.com/mackron/miniaudio.git
synced 2026-04-23 00:34:03 +02:00
Core Audio: Improvements to device enumeration on iOS.
This commit is contained in:
+94
-13
@@ -3211,6 +3211,8 @@ typedef struct
|
|||||||
{
|
{
|
||||||
ma_ios_session_category sessionCategory;
|
ma_ios_session_category sessionCategory;
|
||||||
ma_uint32 sessionCategoryOptions;
|
ma_uint32 sessionCategoryOptions;
|
||||||
|
ma_bool32 noAudioSessionActivate; /* iOS only. When set to true, does not perform an explicit [[AVAudioSession sharedInstace] setActive:true] on initialization. */
|
||||||
|
ma_bool32 noAudioSessionDeactivate; /* iOS only. When set to true, does not perform an explicit [[AVAudioSession sharedInstace] setActive:false] on uninitialization. */
|
||||||
} coreaudio;
|
} coreaudio;
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
@@ -3479,6 +3481,8 @@ struct ma_context
|
|||||||
ma_proc AudioUnitRender;
|
ma_proc AudioUnitRender;
|
||||||
|
|
||||||
/*AudioComponent*/ ma_ptr component;
|
/*AudioComponent*/ ma_ptr component;
|
||||||
|
|
||||||
|
ma_bool32 noAudioSessionDeactivate; /* For tracking whether or not we should explicitly deactivation the audio session on iOS. Set from the config in ma_context_init__coreaudio(). */
|
||||||
} coreaudio;
|
} coreaudio;
|
||||||
#endif
|
#endif
|
||||||
#ifdef MA_SUPPORT_SNDIO
|
#ifdef MA_SUPPORT_SNDIO
|
||||||
@@ -23620,6 +23624,13 @@ static ma_bool32 ma_context_is_device_id_equal__coreaudio(ma_context* pContext,
|
|||||||
return strcmp(pID0->coreaudio, pID1->coreaudio) == 0;
|
return strcmp(pID0->coreaudio, pID1->coreaudio) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void ma_AVAudioSessionPortDescription_to_device_info(AVAudioSessionPortDescription* pPortDesc, ma_device_info* pInfo)
|
||||||
|
{
|
||||||
|
MA_ZERO_OBJECT(pInfo);
|
||||||
|
ma_strncpy_s(pInfo->name, sizeof(pInfo->name), [pPortDesc.portName UTF8String], (size_t)-1);
|
||||||
|
ma_strncpy_s(pInfo->id.coreaudio, sizeof(pInfo->id.coreaudio), [pPortDesc.UID UTF8String], (size_t)-1);
|
||||||
|
}
|
||||||
|
|
||||||
static ma_result ma_context_enumerate_devices__coreaudio(ma_context* pContext, ma_enum_devices_callback_proc callback, void* pUserData)
|
static ma_result ma_context_enumerate_devices__coreaudio(ma_context* pContext, ma_enum_devices_callback_proc callback, void* pUserData)
|
||||||
{
|
{
|
||||||
#if defined(MA_APPLE_DESKTOP)
|
#if defined(MA_APPLE_DESKTOP)
|
||||||
@@ -23659,19 +23670,22 @@ static ma_result ma_context_enumerate_devices__coreaudio(ma_context* pContext, m
|
|||||||
|
|
||||||
ma_free(pDeviceObjectIDs, &pContext->allocationCallbacks);
|
ma_free(pDeviceObjectIDs, &pContext->allocationCallbacks);
|
||||||
#else
|
#else
|
||||||
/* Only supporting default devices on non-Desktop platforms. */
|
|
||||||
ma_device_info info;
|
ma_device_info info;
|
||||||
|
NSArray *pInputs = [[[AVAudioSession sharedInstance] currentRoute] inputs];
|
||||||
|
NSArray *pOutputs = [[[AVAudioSession sharedInstance] currentRoute] outputs];
|
||||||
|
|
||||||
MA_ZERO_OBJECT(&info);
|
for (AVAudioSessionPortDescription* pPortDesc in pOutputs) {
|
||||||
ma_strncpy_s(info.name, sizeof(info.name), MA_DEFAULT_PLAYBACK_DEVICE_NAME, (size_t)-1);
|
ma_AVAudioSessionPortDescription_to_device_info(pPortDesc, &info);
|
||||||
if (!callback(pContext, ma_device_type_playback, &info, pUserData)) {
|
if (!callback(pContext, ma_device_type_playback, &info, pUserData)) {
|
||||||
return MA_SUCCESS;
|
return MA_SUCCESS;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MA_ZERO_OBJECT(&info);
|
for (AVAudioSessionPortDescription* pPortDesc in pInputs) {
|
||||||
ma_strncpy_s(info.name, sizeof(info.name), MA_DEFAULT_CAPTURE_DEVICE_NAME, (size_t)-1);
|
ma_AVAudioSessionPortDescription_to_device_info(pPortDesc, &info);
|
||||||
if (!callback(pContext, ma_device_type_capture, &info, pUserData)) {
|
if (!callback(pContext, ma_device_type_capture, &info, pUserData)) {
|
||||||
return MA_SUCCESS;
|
return MA_SUCCESS;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -23787,12 +23801,41 @@ static ma_result ma_context_get_device_info__coreaudio(ma_context* pContext, ma_
|
|||||||
AudioUnitElement formatElement;
|
AudioUnitElement formatElement;
|
||||||
AudioStreamBasicDescription bestFormat;
|
AudioStreamBasicDescription bestFormat;
|
||||||
UInt32 propSize;
|
UInt32 propSize;
|
||||||
|
|
||||||
if (deviceType == ma_device_type_playback) {
|
/* We want to ensure we use a consistent device name to device enumeration. */
|
||||||
ma_strncpy_s(pDeviceInfo->name, sizeof(pDeviceInfo->name), MA_DEFAULT_PLAYBACK_DEVICE_NAME, (size_t)-1);
|
if (pDeviceID != NULL) {
|
||||||
|
ma_bool32 found = MA_FALSE;
|
||||||
|
if (deviceType == ma_device_type_playback) {
|
||||||
|
NSArray *pOutputs = [[[AVAudioSession sharedInstance] currentRoute] outputs];
|
||||||
|
for (AVAudioSessionPortDescription* pPortDesc in pOutputs) {
|
||||||
|
if (strcmp(pDeviceID->coreaudio, [pPortDesc.UID UTF8String]) == 0) {
|
||||||
|
ma_AVAudioSessionPortDescription_to_device_info(pPortDesc, pDeviceInfo);
|
||||||
|
found = MA_TRUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
NSArray *pInputs = [[[AVAudioSession sharedInstance] currentRoute] inputs];
|
||||||
|
for (AVAudioSessionPortDescription* pPortDesc in pInputs) {
|
||||||
|
if (strcmp(pDeviceID->coreaudio, [pPortDesc.UID UTF8String]) == 0) {
|
||||||
|
ma_AVAudioSessionPortDescription_to_device_info(pPortDesc, pDeviceInfo);
|
||||||
|
found = MA_TRUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!found) {
|
||||||
|
return MA_DOES_NOT_EXIST;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
ma_strncpy_s(pDeviceInfo->name, sizeof(pDeviceInfo->name), MA_DEFAULT_CAPTURE_DEVICE_NAME, (size_t)-1);
|
if (deviceType == ma_device_type_playback) {
|
||||||
|
ma_strncpy_s(pDeviceInfo->name, sizeof(pDeviceInfo->name), MA_DEFAULT_PLAYBACK_DEVICE_NAME, (size_t)-1);
|
||||||
|
} else {
|
||||||
|
ma_strncpy_s(pDeviceInfo->name, sizeof(pDeviceInfo->name), MA_DEFAULT_CAPTURE_DEVICE_NAME, (size_t)-1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Retrieving device information is more annoying on mobile than desktop. For simplicity I'm locking this down to whatever format is
|
Retrieving device information is more annoying on mobile than desktop. For simplicity I'm locking this down to whatever format is
|
||||||
@@ -24594,6 +24637,28 @@ static ma_result ma_device_init_internal__coreaudio(ma_context* pContext, ma_dev
|
|||||||
((ma_AudioComponentInstanceDispose_proc)pContext->coreaudio.AudioComponentInstanceDispose)(pData->audioUnit);
|
((ma_AudioComponentInstanceDispose_proc)pContext->coreaudio.AudioComponentInstanceDispose)(pData->audioUnit);
|
||||||
return ma_result_from_OSStatus(result);
|
return ma_result_from_OSStatus(result);
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
/*
|
||||||
|
For some reason it looks like Apple is only allowing selection of the input device. There does not appear to be any way to change
|
||||||
|
the default output route. I have no idea why this is like this, but for now we'll only be able to configure capture devices.
|
||||||
|
*/
|
||||||
|
if (pDeviceID != NULL) {
|
||||||
|
if (deviceType == ma_device_type_capture) {
|
||||||
|
ma_bool32 found = MA_FALSE;
|
||||||
|
NSArray *pInputs = [[[AVAudioSession sharedInstance] currentRoute] inputs];
|
||||||
|
for (AVAudioSessionPortDescription* pPortDesc in pInputs) {
|
||||||
|
if (strcmp(pDeviceID->coreaudio, [pPortDesc.UID UTF8String]) == 0) {
|
||||||
|
[[AVAudioSession sharedInstance] setPreferredInput:pPortDesc error:nil];
|
||||||
|
found = MA_TRUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (found == MA_FALSE) {
|
||||||
|
return MA_DOES_NOT_EXIST;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -25184,6 +25249,14 @@ static ma_result ma_context_uninit__coreaudio(ma_context* pContext)
|
|||||||
MA_ASSERT(pContext != NULL);
|
MA_ASSERT(pContext != NULL);
|
||||||
MA_ASSERT(pContext->backend == ma_backend_coreaudio);
|
MA_ASSERT(pContext->backend == ma_backend_coreaudio);
|
||||||
|
|
||||||
|
#if defined(MA_APPLE_MOBILE)
|
||||||
|
if (!pContext->coreaudio.noAudioSessionDeactivate) {
|
||||||
|
if (![[AVAudioSession sharedInstance] setActive:false error:nil]) {
|
||||||
|
return ma_context_post_error(pContext, NULL, MA_LOG_LEVEL_ERROR, "Failed to deactivate audio session.", MA_FAILED_TO_INIT_BACKEND);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#if !defined(MA_NO_RUNTIME_LINKING) && !defined(MA_APPLE_MOBILE)
|
#if !defined(MA_NO_RUNTIME_LINKING) && !defined(MA_APPLE_MOBILE)
|
||||||
ma_dlclose(pContext, pContext->coreaudio.hAudioUnit);
|
ma_dlclose(pContext, pContext->coreaudio.hAudioUnit);
|
||||||
ma_dlclose(pContext, pContext->coreaudio.hCoreAudio);
|
ma_dlclose(pContext, pContext->coreaudio.hCoreAudio);
|
||||||
@@ -25260,6 +25333,12 @@ static ma_result ma_context_init__coreaudio(const ma_context_config* pConfig, ma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!pConfig->coreaudio.noAudioSessionActivate) {
|
||||||
|
if (![pAudioSession setActive:true error:nil]) {
|
||||||
|
return ma_context_post_error(pContext, NULL, MA_LOG_LEVEL_ERROR, "Failed to activate audio session.", MA_FAILED_TO_INIT_BACKEND);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -25392,6 +25471,8 @@ static ma_result ma_context_init__coreaudio(const ma_context_config* pConfig, ma
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
pContext->coreaudio.noAudioSessionDeactivate = pConfig->coreaudio.noAudioSessionDeactivate;
|
||||||
|
|
||||||
return MA_SUCCESS;
|
return MA_SUCCESS;
|
||||||
}
|
}
|
||||||
#endif /* Core Audio */
|
#endif /* Core Audio */
|
||||||
|
|||||||
Reference in New Issue
Block a user