diff --git a/README.md b/README.md index 8cd16f9..9060eff 100644 --- a/README.md +++ b/README.md @@ -251,7 +251,6 @@ view `coverage/index.html` in a browser. 0. implement CoreAudio (OSX) backend, get examples working - microphone example - - underflow example 0. ALSA backend for microphone example is broken 0. Add some builtin channel layouts from https://developer.apple.com/library/mac/documentation/MusicAudio/Reference/CoreAudioDataTypesRef/#//apple_ref/doc/constant_group/Audio_Channel_Layout_Tags diff --git a/src/coreaudio.cpp b/src/coreaudio.cpp index fa14cc5..824ab9d 100644 --- a/src/coreaudio.cpp +++ b/src/coreaudio.cpp @@ -839,8 +839,29 @@ static void device_thread_run(void *arg) { } } +static OSStatus on_device_overload(AudioObjectID in_object_id, UInt32 in_number_addresses, + const AudioObjectPropertyAddress in_addresses[], void *in_client_data) +{ + SoundIoOutStreamPrivate *os = (SoundIoOutStreamPrivate *)in_client_data; + SoundIoOutStream *outstream = &os->pub; + outstream->underflow_callback(outstream); + return noErr; +} + static void outstream_destroy_ca(struct SoundIoPrivate *si, struct SoundIoOutStreamPrivate *os) { SoundIoOutStreamCoreAudio *osca = &os->backend_data.coreaudio; + SoundIoOutStream *outstream = &os->pub; + SoundIoDevice *device = outstream->device; + SoundIoDevicePrivate *dev = (SoundIoDevicePrivate *)device; + SoundIoDeviceCoreAudio *dca = &dev->backend_data.coreaudio; + + AudioObjectPropertyAddress prop_address = { + kAudioDeviceProcessorOverload, + kAudioObjectPropertyScopeGlobal, + kAudioObjectPropertyElementMaster + }; + AudioObjectRemovePropertyListener(dca->device_id, &prop_address, on_device_overload, os); + if (osca->output_instance) { AudioOutputUnitStop(osca->output_instance); AudioComponentInstanceDispose(osca->output_instance); @@ -928,6 +949,19 @@ static int outstream_open_ca(struct SoundIoPrivate *si, struct SoundIoOutStreamP return SoundIoErrorOpeningDevice; } + + AudioObjectPropertyAddress prop_address = { + kAudioDeviceProcessorOverload, + kAudioObjectPropertyScopeGlobal, + kAudioObjectPropertyElementMaster + }; + if ((os_err = AudioObjectAddPropertyListener(dca->device_id, &prop_address, + on_device_overload, os))) + { + outstream_destroy_ca(si, os); + return SoundIoErrorOpeningDevice; + } + return 0; }