mirror of
https://github.com/mackron/miniaudio.git
synced 2026-04-22 00:06:59 +02:00
Merge branch 'dev' of https://github.com/dr-soft/miniaudio into dev
This commit is contained in:
+278
-118
@@ -2199,6 +2199,7 @@ struct ma_context
|
||||
ma_proc AudioObjectGetPropertyDataSize;
|
||||
ma_proc AudioObjectSetPropertyData;
|
||||
ma_proc AudioObjectAddPropertyListener;
|
||||
ma_proc AudioObjectRemovePropertyListener;
|
||||
|
||||
ma_handle hAudioUnit; /* Could possibly be set to AudioToolbox on later versions of macOS. */
|
||||
ma_proc AudioComponentFindNext;
|
||||
@@ -17343,6 +17344,7 @@ typedef OSStatus (* ma_AudioObjectGetPropertyData_proc)(AudioObjectID inObjectID
|
||||
typedef OSStatus (* ma_AudioObjectGetPropertyDataSize_proc)(AudioObjectID inObjectID, const AudioObjectPropertyAddress* inAddress, UInt32 inQualifierDataSize, const void* inQualifierData, UInt32* outDataSize);
|
||||
typedef OSStatus (* ma_AudioObjectSetPropertyData_proc)(AudioObjectID inObjectID, const AudioObjectPropertyAddress* inAddress, UInt32 inQualifierDataSize, const void* inQualifierData, UInt32 inDataSize, const void* inData);
|
||||
typedef OSStatus (* ma_AudioObjectAddPropertyListener_proc)(AudioObjectID inObjectID, const AudioObjectPropertyAddress* inAddress, AudioObjectPropertyListenerProc inListener, void* inClientData);
|
||||
typedef OSStatus (* ma_AudioObjectRemovePropertyListener_proc)(AudioObjectID inObjectID, const AudioObjectPropertyAddress* inAddress, AudioObjectPropertyListenerProc inListener, void* inClientData);
|
||||
#endif
|
||||
|
||||
/* AudioToolbox */
|
||||
@@ -18733,28 +18735,6 @@ ma_result ma_context_get_device_info__coreaudio(ma_context* pContext, ma_device_
|
||||
}
|
||||
|
||||
|
||||
void ma_device_uninit__coreaudio(ma_device* pDevice)
|
||||
{
|
||||
ma_assert(pDevice != NULL);
|
||||
ma_assert(ma_device__get_state(pDevice) == MA_STATE_UNINITIALIZED);
|
||||
|
||||
if (pDevice->coreaudio.audioUnitCapture != NULL) {
|
||||
((ma_AudioComponentInstanceDispose_proc)pDevice->pContext->coreaudio.AudioComponentInstanceDispose)((AudioUnit)pDevice->coreaudio.audioUnitCapture);
|
||||
}
|
||||
if (pDevice->coreaudio.audioUnitPlayback != NULL) {
|
||||
((ma_AudioComponentInstanceDispose_proc)pDevice->pContext->coreaudio.AudioComponentInstanceDispose)((AudioUnit)pDevice->coreaudio.audioUnitPlayback);
|
||||
}
|
||||
|
||||
if (pDevice->coreaudio.pAudioBufferList) {
|
||||
ma_free(pDevice->coreaudio.pAudioBufferList);
|
||||
}
|
||||
|
||||
if (pDevice->type == ma_device_type_duplex) {
|
||||
ma_pcm_rb_uninit(&pDevice->coreaudio.duplexRB);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
OSStatus ma_on_output__coreaudio(void* pUserData, AudioUnitRenderActionFlags* pActionFlags, const AudioTimeStamp* pTimeStamp, UInt32 busNumber, UInt32 frameCount, AudioBufferList* pBufferList)
|
||||
{
|
||||
ma_device* pDevice = (ma_device*)pUserData;
|
||||
@@ -19027,10 +19007,15 @@ void on_start_stop__coreaudio(void* pUserData, AudioUnit audioUnit, AudioUnitPro
|
||||
}
|
||||
|
||||
#if defined(MA_APPLE_DESKTOP)
|
||||
static ma_uint32 g_DeviceTrackingInitCounter_CoreAudio = 0;
|
||||
static ma_mutex g_DeviceTrackingMutex_CoreAudio;
|
||||
static ma_device** g_ppTrackedDevices_CoreAudio = NULL;
|
||||
static ma_uint32 g_TrackedDeviceCap_CoreAudio = 0;
|
||||
static ma_uint32 g_TrackedDeviceCount_CoreAudio = 0;
|
||||
|
||||
OSStatus ma_default_device_changed__coreaudio(AudioObjectID objectID, UInt32 addressCount, const AudioObjectPropertyAddress* pAddresses, void* pUserData)
|
||||
{
|
||||
ma_device* pDevice = (ma_device*)pUserData;
|
||||
ma_assert(pDevice != NULL);
|
||||
ma_device_type deviceType;
|
||||
|
||||
/* Not sure if I really need to check this, but it makes me feel better. */
|
||||
if (addressCount == 0) {
|
||||
@@ -19038,56 +19023,223 @@ OSStatus ma_default_device_changed__coreaudio(AudioObjectID objectID, UInt32 add
|
||||
}
|
||||
|
||||
if (pAddresses[0].mSelector == kAudioHardwarePropertyDefaultOutputDevice) {
|
||||
ma_result reinitResult;
|
||||
|
||||
pDevice->coreaudio.isSwitchingPlaybackDevice = MA_TRUE;
|
||||
reinitResult = ma_device_reinit_internal__coreaudio(pDevice, ma_device_type_playback, MA_TRUE);
|
||||
pDevice->coreaudio.isSwitchingPlaybackDevice = MA_FALSE;
|
||||
|
||||
if (reinitResult == MA_SUCCESS) {
|
||||
ma_device__post_init_setup(pDevice, ma_device_type_playback);
|
||||
|
||||
/* Restart the device if required. If this fails we need to stop the device entirely. */
|
||||
if (ma_device__get_state(pDevice) == MA_STATE_STARTED) {
|
||||
OSStatus status = ((ma_AudioOutputUnitStart_proc)pDevice->pContext->coreaudio.AudioOutputUnitStart)((AudioUnit)pDevice->coreaudio.audioUnitPlayback);
|
||||
if (status != noErr) {
|
||||
if (pDevice->type == ma_device_type_duplex) {
|
||||
((ma_AudioOutputUnitStop_proc)pDevice->pContext->coreaudio.AudioOutputUnitStop)((AudioUnit)pDevice->coreaudio.audioUnitCapture);
|
||||
}
|
||||
ma_device__set_state(pDevice, MA_STATE_STOPPED);
|
||||
}
|
||||
}
|
||||
}
|
||||
deviceType = ma_device_type_playback;
|
||||
} else if (pAddresses[0].mSelector == kAudioHardwarePropertyDefaultInputDevice) {
|
||||
deviceType = ma_device_type_capture;
|
||||
} else {
|
||||
return noErr; /* Should never hit this. */
|
||||
}
|
||||
|
||||
if (pAddresses[0].mSelector == kAudioHardwarePropertyDefaultInputDevice) {
|
||||
ma_result reinitResult;
|
||||
|
||||
pDevice->coreaudio.isSwitchingPlaybackDevice = MA_TRUE;
|
||||
reinitResult = ma_device_reinit_internal__coreaudio(pDevice, ma_device_type_capture, MA_TRUE);
|
||||
pDevice->coreaudio.isSwitchingPlaybackDevice = MA_FALSE;
|
||||
|
||||
if (reinitResult == MA_SUCCESS) {
|
||||
ma_device__post_init_setup(pDevice, ma_device_type_capture);
|
||||
ma_mutex_lock(&g_DeviceTrackingMutex_CoreAudio);
|
||||
{
|
||||
ma_uint32 iDevice;
|
||||
for (iDevice = 0; iDevice < g_TrackedDeviceCount_CoreAudio; iDevice += 1) {
|
||||
ma_result reinitResult;
|
||||
ma_device* pDevice;
|
||||
|
||||
/* Restart the device if required. If this fails we need to stop the device entirely. */
|
||||
if (ma_device__get_state(pDevice) == MA_STATE_STARTED) {
|
||||
OSStatus status = ((ma_AudioOutputUnitStart_proc)pDevice->pContext->coreaudio.AudioOutputUnitStart)((AudioUnit)pDevice->coreaudio.audioUnitCapture);
|
||||
if (status != noErr) {
|
||||
if (pDevice->type == ma_device_type_duplex) {
|
||||
((ma_AudioOutputUnitStop_proc)pDevice->pContext->coreaudio.AudioOutputUnitStop)((AudioUnit)pDevice->coreaudio.audioUnitPlayback);
|
||||
pDevice = g_ppTrackedDevices_CoreAudio[iDevice];
|
||||
if (pDevice->type == deviceType || pDevice->type == ma_device_type_duplex) {
|
||||
if (deviceType == ma_device_type_playback) {
|
||||
pDevice->coreaudio.isSwitchingPlaybackDevice = MA_TRUE;
|
||||
reinitResult = ma_device_reinit_internal__coreaudio(pDevice, deviceType, MA_TRUE);
|
||||
pDevice->coreaudio.isSwitchingPlaybackDevice = MA_FALSE;
|
||||
} else {
|
||||
pDevice->coreaudio.isSwitchingCaptureDevice = MA_TRUE;
|
||||
reinitResult = ma_device_reinit_internal__coreaudio(pDevice, deviceType, MA_TRUE);
|
||||
pDevice->coreaudio.isSwitchingCaptureDevice = MA_FALSE;
|
||||
}
|
||||
|
||||
if (reinitResult == MA_SUCCESS) {
|
||||
ma_device__post_init_setup(pDevice, deviceType);
|
||||
|
||||
/* Restart the device if required. If this fails we need to stop the device entirely. */
|
||||
if (ma_device__get_state(pDevice) == MA_STATE_STARTED) {
|
||||
OSStatus status;
|
||||
if (deviceType == ma_device_type_playback) {
|
||||
status = ((ma_AudioOutputUnitStart_proc)pDevice->pContext->coreaudio.AudioOutputUnitStart)((AudioUnit)pDevice->coreaudio.audioUnitPlayback);
|
||||
if (status != noErr) {
|
||||
if (pDevice->type == ma_device_type_duplex) {
|
||||
((ma_AudioOutputUnitStop_proc)pDevice->pContext->coreaudio.AudioOutputUnitStop)((AudioUnit)pDevice->coreaudio.audioUnitCapture);
|
||||
}
|
||||
ma_device__set_state(pDevice, MA_STATE_STOPPED);
|
||||
}
|
||||
} else if (deviceType == ma_device_type_capture) {
|
||||
status = ((ma_AudioOutputUnitStart_proc)pDevice->pContext->coreaudio.AudioOutputUnitStart)((AudioUnit)pDevice->coreaudio.audioUnitCapture);
|
||||
if (status != noErr) {
|
||||
if (pDevice->type == ma_device_type_duplex) {
|
||||
((ma_AudioOutputUnitStop_proc)pDevice->pContext->coreaudio.AudioOutputUnitStop)((AudioUnit)pDevice->coreaudio.audioUnitPlayback);
|
||||
}
|
||||
ma_device__set_state(pDevice, MA_STATE_STOPPED);
|
||||
}
|
||||
}
|
||||
}
|
||||
ma_device__set_state(pDevice, MA_STATE_STOPPED);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ma_mutex_unlock(&g_DeviceTrackingMutex_CoreAudio);
|
||||
|
||||
(void)objectID; /* Unused. */
|
||||
return noErr;
|
||||
}
|
||||
|
||||
static ma_result ma_context__init_device_tracking__coreaudio(ma_context* pContext)
|
||||
{
|
||||
ma_assert(pContext != NULL);
|
||||
|
||||
if (ma_atomic_increment_32(&g_DeviceTrackingInitCounter_CoreAudio) == 1) {
|
||||
AudioObjectPropertyAddress propAddress;
|
||||
propAddress.mScope = kAudioObjectPropertyScopeGlobal;
|
||||
propAddress.mElement = kAudioObjectPropertyElementMaster;
|
||||
|
||||
ma_mutex_init(pContext, &g_DeviceTrackingMutex_CoreAudio);
|
||||
|
||||
propAddress.mSelector = kAudioHardwarePropertyDefaultInputDevice;
|
||||
((ma_AudioObjectAddPropertyListener_proc)pContext->coreaudio.AudioObjectAddPropertyListener)(kAudioObjectSystemObject, &propAddress, &ma_default_device_changed__coreaudio, NULL);
|
||||
|
||||
propAddress.mSelector = kAudioHardwarePropertyDefaultOutputDevice;
|
||||
((ma_AudioObjectAddPropertyListener_proc)pContext->coreaudio.AudioObjectAddPropertyListener)(kAudioObjectSystemObject, &propAddress, &ma_default_device_changed__coreaudio, NULL);
|
||||
}
|
||||
|
||||
return MA_SUCCESS;
|
||||
}
|
||||
|
||||
static ma_result ma_context__uninit_device_tracking__coreaudio(ma_context* pContext)
|
||||
{
|
||||
ma_assert(pContext != NULL);
|
||||
|
||||
if (ma_atomic_decrement_32(&g_DeviceTrackingInitCounter_CoreAudio) == 0) {
|
||||
AudioObjectPropertyAddress propAddress;
|
||||
propAddress.mScope = kAudioObjectPropertyScopeGlobal;
|
||||
propAddress.mElement = kAudioObjectPropertyElementMaster;
|
||||
|
||||
propAddress.mSelector = kAudioHardwarePropertyDefaultInputDevice;
|
||||
((ma_AudioObjectRemovePropertyListener_proc)pContext->coreaudio.AudioObjectRemovePropertyListener)(kAudioObjectSystemObject, &propAddress, &ma_default_device_changed__coreaudio, NULL);
|
||||
|
||||
propAddress.mSelector = kAudioHardwarePropertyDefaultOutputDevice;
|
||||
((ma_AudioObjectRemovePropertyListener_proc)pContext->coreaudio.AudioObjectRemovePropertyListener)(kAudioObjectSystemObject, &propAddress, &ma_default_device_changed__coreaudio, NULL);
|
||||
|
||||
/* At this point there should be no tracked devices. If so there's an error somewhere. */
|
||||
ma_assert(g_ppTrackedDevices_CoreAudio == NULL);
|
||||
ma_assert(g_TrackedDeviceCount_CoreAudio == 0);
|
||||
|
||||
ma_mutex_uninit(&g_DeviceTrackingMutex_CoreAudio);
|
||||
}
|
||||
|
||||
return MA_SUCCESS;
|
||||
}
|
||||
|
||||
static ma_result ma_device__track__coreaudio(ma_device* pDevice)
|
||||
{
|
||||
ma_result result;
|
||||
|
||||
ma_assert(pDevice != NULL);
|
||||
|
||||
result = ma_context__init_device_tracking__coreaudio(pDevice->pContext);
|
||||
if (result != MA_SUCCESS) {
|
||||
return result;
|
||||
}
|
||||
|
||||
ma_mutex_lock(&g_DeviceTrackingMutex_CoreAudio);
|
||||
{
|
||||
/* Allocate memory if required. */
|
||||
if (g_TrackedDeviceCap_CoreAudio <= g_TrackedDeviceCount_CoreAudio) {
|
||||
ma_uint32 newCap;
|
||||
ma_device** ppNewDevices;
|
||||
|
||||
newCap = g_TrackedDeviceCap_CoreAudio * 2;
|
||||
if (newCap == 0) {
|
||||
newCap = 1;
|
||||
}
|
||||
|
||||
ppNewDevices = (ma_device**)ma_realloc(g_ppTrackedDevices_CoreAudio, sizeof(*g_ppTrackedDevices_CoreAudio) * newCap);
|
||||
if (ppNewDevices == NULL) {
|
||||
ma_mutex_unlock(&g_DeviceTrackingMutex_CoreAudio);
|
||||
return MA_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
g_ppTrackedDevices_CoreAudio = ppNewDevices;
|
||||
g_TrackedDeviceCap_CoreAudio = newCap;
|
||||
}
|
||||
|
||||
g_ppTrackedDevices_CoreAudio[g_TrackedDeviceCount_CoreAudio] = pDevice;
|
||||
g_TrackedDeviceCount_CoreAudio += 1;
|
||||
}
|
||||
ma_mutex_unlock(&g_DeviceTrackingMutex_CoreAudio);
|
||||
|
||||
return MA_SUCCESS;
|
||||
}
|
||||
|
||||
static ma_result ma_device__untrack__coreaudio(ma_device* pDevice)
|
||||
{
|
||||
ma_result result;
|
||||
|
||||
ma_assert(pDevice != NULL);
|
||||
|
||||
ma_mutex_lock(&g_DeviceTrackingMutex_CoreAudio);
|
||||
{
|
||||
ma_uint32 iDevice;
|
||||
for (iDevice = 0; iDevice < g_TrackedDeviceCount_CoreAudio; iDevice += 1) {
|
||||
if (g_ppTrackedDevices_CoreAudio[iDevice] == pDevice) {
|
||||
/* We've found the device. We now need to remove it from the list. */
|
||||
ma_uint32 jDevice;
|
||||
for (jDevice = iDevice; jDevice < g_TrackedDeviceCount_CoreAudio-1; jDevice += 1) {
|
||||
g_ppTrackedDevices_CoreAudio[jDevice] = g_ppTrackedDevices_CoreAudio[jDevice+1];
|
||||
}
|
||||
|
||||
g_TrackedDeviceCount_CoreAudio -= 1;
|
||||
|
||||
/* If there's nothing else in the list we need to free memory. */
|
||||
if (g_TrackedDeviceCount_CoreAudio == 0) {
|
||||
ma_free(g_ppTrackedDevices_CoreAudio);
|
||||
g_ppTrackedDevices_CoreAudio = NULL;
|
||||
g_TrackedDeviceCap_CoreAudio = 0;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
ma_mutex_unlock(&g_DeviceTrackingMutex_CoreAudio);
|
||||
|
||||
result = ma_context__uninit_device_tracking__coreaudio(pDevice->pContext);
|
||||
if (result != MA_SUCCESS) {
|
||||
return result;
|
||||
}
|
||||
|
||||
return MA_SUCCESS;
|
||||
}
|
||||
#endif
|
||||
|
||||
void ma_device_uninit__coreaudio(ma_device* pDevice)
|
||||
{
|
||||
ma_assert(pDevice != NULL);
|
||||
ma_assert(ma_device__get_state(pDevice) == MA_STATE_UNINITIALIZED);
|
||||
|
||||
#if defined(MA_APPLE_DESKTOP)
|
||||
/*
|
||||
Make sure we're no longer tracking the device. It doesn't matter if we call this for a non-default device because it'll
|
||||
just gracefully ignore it.
|
||||
*/
|
||||
ma_device__untrack__coreaudio(pDevice);
|
||||
#endif
|
||||
|
||||
if (pDevice->coreaudio.audioUnitCapture != NULL) {
|
||||
((ma_AudioComponentInstanceDispose_proc)pDevice->pContext->coreaudio.AudioComponentInstanceDispose)((AudioUnit)pDevice->coreaudio.audioUnitCapture);
|
||||
}
|
||||
if (pDevice->coreaudio.audioUnitPlayback != NULL) {
|
||||
((ma_AudioComponentInstanceDispose_proc)pDevice->pContext->coreaudio.AudioComponentInstanceDispose)((AudioUnit)pDevice->coreaudio.audioUnitPlayback);
|
||||
}
|
||||
|
||||
if (pDevice->coreaudio.pAudioBufferList) {
|
||||
ma_free(pDevice->coreaudio.pAudioBufferList);
|
||||
}
|
||||
|
||||
if (pDevice->type == ma_device_type_duplex) {
|
||||
ma_pcm_rb_uninit(&pDevice->coreaudio.duplexRB);
|
||||
}
|
||||
}
|
||||
|
||||
typedef struct
|
||||
{
|
||||
/* Input. */
|
||||
@@ -19486,14 +19638,7 @@ ma_result ma_device_reinit_internal__coreaudio(ma_device* pDevice, ma_device_typ
|
||||
if (pDevice->coreaudio.pAudioBufferList) {
|
||||
ma_free(pDevice->coreaudio.pAudioBufferList);
|
||||
}
|
||||
|
||||
#if defined(MA_APPLE_DESKTOP)
|
||||
pDevice->coreaudio.deviceObjectIDCapture = (ma_uint32)data.deviceObjectID;
|
||||
#endif
|
||||
pDevice->coreaudio.audioUnitCapture = (ma_ptr)data.audioUnit;
|
||||
pDevice->coreaudio.pAudioBufferList = (ma_ptr)data.pAudioBufferList;
|
||||
}
|
||||
if (deviceType == ma_device_type_playback) {
|
||||
} else if (deviceType == ma_device_type_playback) {
|
||||
data.formatIn = pDevice->playback.format;
|
||||
data.channelsIn = pDevice->playback.channels;
|
||||
data.sampleRateIn = pDevice->sampleRate;
|
||||
@@ -19509,11 +19654,6 @@ ma_result ma_device_reinit_internal__coreaudio(ma_device* pDevice, ma_device_typ
|
||||
((ma_AudioOutputUnitStop_proc)pDevice->pContext->coreaudio.AudioOutputUnitStop)((AudioUnit)pDevice->coreaudio.audioUnitPlayback);
|
||||
((ma_AudioComponentInstanceDispose_proc)pDevice->pContext->coreaudio.AudioComponentInstanceDispose)((AudioUnit)pDevice->coreaudio.audioUnitPlayback);
|
||||
}
|
||||
|
||||
#if defined(MA_APPLE_DESKTOP)
|
||||
pDevice->coreaudio.deviceObjectIDPlayback = (ma_uint32)data.deviceObjectID;
|
||||
#endif
|
||||
pDevice->coreaudio.audioUnitPlayback = (ma_ptr)data.audioUnit;
|
||||
}
|
||||
data.bufferSizeInFramesIn = pDevice->coreaudio.originalBufferSizeInFrames;
|
||||
data.bufferSizeInMillisecondsIn = pDevice->coreaudio.originalBufferSizeInMilliseconds;
|
||||
@@ -19524,6 +19664,33 @@ ma_result ma_device_reinit_internal__coreaudio(ma_device* pDevice, ma_device_typ
|
||||
return result;
|
||||
}
|
||||
|
||||
if (deviceType == ma_device_type_capture) {
|
||||
#if defined(MA_APPLE_DESKTOP)
|
||||
pDevice->coreaudio.deviceObjectIDCapture = (ma_uint32)data.deviceObjectID;
|
||||
#endif
|
||||
pDevice->coreaudio.audioUnitCapture = (ma_ptr)data.audioUnit;
|
||||
pDevice->coreaudio.pAudioBufferList = (ma_ptr)data.pAudioBufferList;
|
||||
|
||||
pDevice->capture.internalFormat = data.formatOut;
|
||||
pDevice->capture.internalChannels = data.channelsOut;
|
||||
pDevice->capture.internalSampleRate = data.sampleRateOut;
|
||||
ma_copy_memory(pDevice->capture.internalChannelMap, data.channelMapOut, sizeof(data.channelMapOut));
|
||||
pDevice->capture.internalBufferSizeInFrames = data.bufferSizeInFramesOut;
|
||||
pDevice->capture.internalPeriods = data.periodsOut;
|
||||
} else if (deviceType == ma_device_type_playback) {
|
||||
#if defined(MA_APPLE_DESKTOP)
|
||||
pDevice->coreaudio.deviceObjectIDPlayback = (ma_uint32)data.deviceObjectID;
|
||||
#endif
|
||||
pDevice->coreaudio.audioUnitPlayback = (ma_ptr)data.audioUnit;
|
||||
|
||||
pDevice->playback.internalFormat = data.formatOut;
|
||||
pDevice->playback.internalChannels = data.channelsOut;
|
||||
pDevice->playback.internalSampleRate = data.sampleRateOut;
|
||||
ma_copy_memory(pDevice->playback.internalChannelMap, data.channelMapOut, sizeof(data.channelMapOut));
|
||||
pDevice->playback.internalBufferSizeInFrames = data.bufferSizeInFramesOut;
|
||||
pDevice->playback.internalPeriods = data.periodsOut;
|
||||
}
|
||||
|
||||
return MA_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -19581,18 +19748,13 @@ ma_result ma_device_init__coreaudio(ma_context* pContext, const ma_device_config
|
||||
pDevice->capture.internalBufferSizeInFrames = data.bufferSizeInFramesOut;
|
||||
pDevice->capture.internalPeriods = data.periodsOut;
|
||||
|
||||
/* TODO: This needs to be made global. */
|
||||
#if defined(MA_APPLE_DESKTOP)
|
||||
/*
|
||||
If we are using the default device we'll need to listen for changes to the system's default device so we can seemlessly
|
||||
switch the device in the background.
|
||||
*/
|
||||
if (pConfig->capture.pDeviceID == NULL) {
|
||||
AudioObjectPropertyAddress propAddress;
|
||||
propAddress.mSelector = kAudioHardwarePropertyDefaultInputDevice;
|
||||
propAddress.mScope = kAudioObjectPropertyScopeGlobal;
|
||||
propAddress.mElement = kAudioObjectPropertyElementMaster;
|
||||
((ma_AudioObjectAddPropertyListener_proc)pDevice->pContext->coreaudio.AudioObjectAddPropertyListener)(kAudioObjectSystemObject, &propAddress, &ma_default_device_changed__coreaudio, pDevice);
|
||||
ma_device__track__coreaudio(pDevice);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -19646,18 +19808,13 @@ ma_result ma_device_init__coreaudio(ma_context* pContext, const ma_device_config
|
||||
pDevice->playback.internalBufferSizeInFrames = data.bufferSizeInFramesOut;
|
||||
pDevice->playback.internalPeriods = data.periodsOut;
|
||||
|
||||
/* TODO: This needs to be made global. */
|
||||
#if defined(MA_APPLE_DESKTOP)
|
||||
/*
|
||||
If we are using the default device we'll need to listen for changes to the system's default device so we can seemlessly
|
||||
switch the device in the background.
|
||||
*/
|
||||
if (pConfig->playback.pDeviceID == NULL) {
|
||||
AudioObjectPropertyAddress propAddress;
|
||||
propAddress.mSelector = kAudioHardwarePropertyDefaultOutputDevice;
|
||||
propAddress.mScope = kAudioObjectPropertyScopeGlobal;
|
||||
propAddress.mElement = kAudioObjectPropertyElementMaster;
|
||||
((ma_AudioObjectAddPropertyListener_proc)pDevice->pContext->coreaudio.AudioObjectAddPropertyListener)(kAudioObjectSystemObject, &propAddress, &ma_default_device_changed__coreaudio, pDevice);
|
||||
if (pConfig->playback.pDeviceID == NULL && (pConfig->deviceType != ma_device_type_duplex || pConfig->capture.pDeviceID != NULL)) {
|
||||
ma_device__track__coreaudio(pDevice);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -19785,10 +19942,11 @@ ma_result ma_context_init__coreaudio(const ma_context_config* pConfig, ma_contex
|
||||
return MA_API_NOT_FOUND;
|
||||
}
|
||||
|
||||
pContext->coreaudio.AudioObjectGetPropertyData = ma_dlsym(pContext, pContext->coreaudio.hCoreAudio, "AudioObjectGetPropertyData");
|
||||
pContext->coreaudio.AudioObjectGetPropertyDataSize = ma_dlsym(pContext, pContext->coreaudio.hCoreAudio, "AudioObjectGetPropertyDataSize");
|
||||
pContext->coreaudio.AudioObjectSetPropertyData = ma_dlsym(pContext, pContext->coreaudio.hCoreAudio, "AudioObjectSetPropertyData");
|
||||
pContext->coreaudio.AudioObjectAddPropertyListener = ma_dlsym(pContext, pContext->coreaudio.hCoreAudio, "AudioObjectAddPropertyListener");
|
||||
pContext->coreaudio.AudioObjectGetPropertyData = ma_dlsym(pContext, pContext->coreaudio.hCoreAudio, "AudioObjectGetPropertyData");
|
||||
pContext->coreaudio.AudioObjectGetPropertyDataSize = ma_dlsym(pContext, pContext->coreaudio.hCoreAudio, "AudioObjectGetPropertyDataSize");
|
||||
pContext->coreaudio.AudioObjectSetPropertyData = ma_dlsym(pContext, pContext->coreaudio.hCoreAudio, "AudioObjectSetPropertyData");
|
||||
pContext->coreaudio.AudioObjectAddPropertyListener = ma_dlsym(pContext, pContext->coreaudio.hCoreAudio, "AudioObjectAddPropertyListener");
|
||||
pContext->coreaudio.AudioObjectRemovePropertyListener = ma_dlsym(pContext, pContext->coreaudio.hCoreAudio, "AudioObjectRemovePropertyListener");
|
||||
|
||||
/*
|
||||
It looks like Apple has moved some APIs from AudioUnit into AudioToolbox on more recent versions of macOS. They are still
|
||||
@@ -19814,39 +19972,40 @@ ma_result ma_context_init__coreaudio(const ma_context_config* pConfig, ma_contex
|
||||
}
|
||||
}
|
||||
|
||||
pContext->coreaudio.AudioComponentFindNext = ma_dlsym(pContext, pContext->coreaudio.hAudioUnit, "AudioComponentFindNext");
|
||||
pContext->coreaudio.AudioComponentInstanceDispose = ma_dlsym(pContext, pContext->coreaudio.hAudioUnit, "AudioComponentInstanceDispose");
|
||||
pContext->coreaudio.AudioComponentInstanceNew = ma_dlsym(pContext, pContext->coreaudio.hAudioUnit, "AudioComponentInstanceNew");
|
||||
pContext->coreaudio.AudioOutputUnitStart = ma_dlsym(pContext, pContext->coreaudio.hAudioUnit, "AudioOutputUnitStart");
|
||||
pContext->coreaudio.AudioOutputUnitStop = ma_dlsym(pContext, pContext->coreaudio.hAudioUnit, "AudioOutputUnitStop");
|
||||
pContext->coreaudio.AudioUnitAddPropertyListener = ma_dlsym(pContext, pContext->coreaudio.hAudioUnit, "AudioUnitAddPropertyListener");
|
||||
pContext->coreaudio.AudioUnitGetPropertyInfo = ma_dlsym(pContext, pContext->coreaudio.hAudioUnit, "AudioUnitGetPropertyInfo");
|
||||
pContext->coreaudio.AudioUnitGetProperty = ma_dlsym(pContext, pContext->coreaudio.hAudioUnit, "AudioUnitGetProperty");
|
||||
pContext->coreaudio.AudioUnitSetProperty = ma_dlsym(pContext, pContext->coreaudio.hAudioUnit, "AudioUnitSetProperty");
|
||||
pContext->coreaudio.AudioUnitInitialize = ma_dlsym(pContext, pContext->coreaudio.hAudioUnit, "AudioUnitInitialize");
|
||||
pContext->coreaudio.AudioUnitRender = ma_dlsym(pContext, pContext->coreaudio.hAudioUnit, "AudioUnitRender");
|
||||
pContext->coreaudio.AudioComponentFindNext = ma_dlsym(pContext, pContext->coreaudio.hAudioUnit, "AudioComponentFindNext");
|
||||
pContext->coreaudio.AudioComponentInstanceDispose = ma_dlsym(pContext, pContext->coreaudio.hAudioUnit, "AudioComponentInstanceDispose");
|
||||
pContext->coreaudio.AudioComponentInstanceNew = ma_dlsym(pContext, pContext->coreaudio.hAudioUnit, "AudioComponentInstanceNew");
|
||||
pContext->coreaudio.AudioOutputUnitStart = ma_dlsym(pContext, pContext->coreaudio.hAudioUnit, "AudioOutputUnitStart");
|
||||
pContext->coreaudio.AudioOutputUnitStop = ma_dlsym(pContext, pContext->coreaudio.hAudioUnit, "AudioOutputUnitStop");
|
||||
pContext->coreaudio.AudioUnitAddPropertyListener = ma_dlsym(pContext, pContext->coreaudio.hAudioUnit, "AudioUnitAddPropertyListener");
|
||||
pContext->coreaudio.AudioUnitGetPropertyInfo = ma_dlsym(pContext, pContext->coreaudio.hAudioUnit, "AudioUnitGetPropertyInfo");
|
||||
pContext->coreaudio.AudioUnitGetProperty = ma_dlsym(pContext, pContext->coreaudio.hAudioUnit, "AudioUnitGetProperty");
|
||||
pContext->coreaudio.AudioUnitSetProperty = ma_dlsym(pContext, pContext->coreaudio.hAudioUnit, "AudioUnitSetProperty");
|
||||
pContext->coreaudio.AudioUnitInitialize = ma_dlsym(pContext, pContext->coreaudio.hAudioUnit, "AudioUnitInitialize");
|
||||
pContext->coreaudio.AudioUnitRender = ma_dlsym(pContext, pContext->coreaudio.hAudioUnit, "AudioUnitRender");
|
||||
#else
|
||||
pContext->coreaudio.CFStringGetCString = (ma_proc)CFStringGetCString;
|
||||
pContext->coreaudio.CFRelease = (ma_proc)CFRelease;
|
||||
pContext->coreaudio.CFStringGetCString = (ma_proc)CFStringGetCString;
|
||||
pContext->coreaudio.CFRelease = (ma_proc)CFRelease;
|
||||
|
||||
#if defined(MA_APPLE_DESKTOP)
|
||||
pContext->coreaudio.AudioObjectGetPropertyData = (ma_proc)AudioObjectGetPropertyData;
|
||||
pContext->coreaudio.AudioObjectGetPropertyDataSize = (ma_proc)AudioObjectGetPropertyDataSize;
|
||||
pContext->coreaudio.AudioObjectSetPropertyData = (ma_proc)AudioObjectSetPropertyData;
|
||||
pContext->coreaudio.AudioObjectAddPropertyListener = (ma_proc)AudioObjectAddPropertyListener;
|
||||
pContext->coreaudio.AudioObjectGetPropertyData = (ma_proc)AudioObjectGetPropertyData;
|
||||
pContext->coreaudio.AudioObjectGetPropertyDataSize = (ma_proc)AudioObjectGetPropertyDataSize;
|
||||
pContext->coreaudio.AudioObjectSetPropertyData = (ma_proc)AudioObjectSetPropertyData;
|
||||
pContext->coreaudio.AudioObjectAddPropertyListener = (ma_proc)AudioObjectAddPropertyListener;
|
||||
pContext->coreaudio.AudioObjectRemovePropertyListener = (ma_proc)AudioObjectRemovePropertyListener;
|
||||
#endif
|
||||
|
||||
pContext->coreaudio.AudioComponentFindNext = (ma_proc)AudioComponentFindNext;
|
||||
pContext->coreaudio.AudioComponentInstanceDispose = (ma_proc)AudioComponentInstanceDispose;
|
||||
pContext->coreaudio.AudioComponentInstanceNew = (ma_proc)AudioComponentInstanceNew;
|
||||
pContext->coreaudio.AudioOutputUnitStart = (ma_proc)AudioOutputUnitStart;
|
||||
pContext->coreaudio.AudioOutputUnitStop = (ma_proc)AudioOutputUnitStop;
|
||||
pContext->coreaudio.AudioUnitAddPropertyListener = (ma_proc)AudioUnitAddPropertyListener;
|
||||
pContext->coreaudio.AudioUnitGetPropertyInfo = (ma_proc)AudioUnitGetPropertyInfo;
|
||||
pContext->coreaudio.AudioUnitGetProperty = (ma_proc)AudioUnitGetProperty;
|
||||
pContext->coreaudio.AudioUnitSetProperty = (ma_proc)AudioUnitSetProperty;
|
||||
pContext->coreaudio.AudioUnitInitialize = (ma_proc)AudioUnitInitialize;
|
||||
pContext->coreaudio.AudioUnitRender = (ma_proc)AudioUnitRender;
|
||||
pContext->coreaudio.AudioComponentFindNext = (ma_proc)AudioComponentFindNext;
|
||||
pContext->coreaudio.AudioComponentInstanceDispose = (ma_proc)AudioComponentInstanceDispose;
|
||||
pContext->coreaudio.AudioComponentInstanceNew = (ma_proc)AudioComponentInstanceNew;
|
||||
pContext->coreaudio.AudioOutputUnitStart = (ma_proc)AudioOutputUnitStart;
|
||||
pContext->coreaudio.AudioOutputUnitStop = (ma_proc)AudioOutputUnitStop;
|
||||
pContext->coreaudio.AudioUnitAddPropertyListener = (ma_proc)AudioUnitAddPropertyListener;
|
||||
pContext->coreaudio.AudioUnitGetPropertyInfo = (ma_proc)AudioUnitGetPropertyInfo;
|
||||
pContext->coreaudio.AudioUnitGetProperty = (ma_proc)AudioUnitGetProperty;
|
||||
pContext->coreaudio.AudioUnitSetProperty = (ma_proc)AudioUnitSetProperty;
|
||||
pContext->coreaudio.AudioUnitInitialize = (ma_proc)AudioUnitInitialize;
|
||||
pContext->coreaudio.AudioUnitRender = (ma_proc)AudioUnitRender;
|
||||
#endif
|
||||
|
||||
pContext->isBackendAsynchronous = MA_TRUE;
|
||||
@@ -34675,6 +34834,7 @@ REVISION HISTORY
|
||||
v0.9.8 - 2019-xx-xx
|
||||
- WASAPI: Fix a potential deadlock when starting a full-duplex device.
|
||||
- WASAPI: Enable automatic resampling by default. Disable with config.wasapi.noAutoConvertSRC.
|
||||
- Core Audio: Fix bugs with automatic stream routing.
|
||||
- Fix some uncommon warnings emitted by GCC when `__inline__` is undefined or defined as nothing.
|
||||
|
||||
v0.9.7 - 2019-08-28
|
||||
|
||||
Reference in New Issue
Block a user