summaryrefslogtreecommitdiff
path: root/libs/backends/coreaudio/coreaudio_pcmio.cc
diff options
context:
space:
mode:
authorRobin Gareus <robin@gareus.org>2015-03-06 21:26:07 +0100
committerRobin Gareus <robin@gareus.org>2015-03-06 23:26:05 +0100
commit13bad670facd14ab63dccb8b1a0f1c7b8498e6bf (patch)
tree231987bfd57d21c5fe23e1fd35b9557102c7c709 /libs/backends/coreaudio/coreaudio_pcmio.cc
parent3b941fc0fa23d5612497a99771676ac70fdd10ad (diff)
more ongoing work on the coreaudio backend
* audio port names * latency compensation * xrun reporting * various fixes and cleanup
Diffstat (limited to 'libs/backends/coreaudio/coreaudio_pcmio.cc')
-rw-r--r--libs/backends/coreaudio/coreaudio_pcmio.cc145
1 files changed, 110 insertions, 35 deletions
diff --git a/libs/backends/coreaudio/coreaudio_pcmio.cc b/libs/backends/coreaudio/coreaudio_pcmio.cc
index 29207d4ffa..7f9322bc1f 100644
--- a/libs/backends/coreaudio/coreaudio_pcmio.cc
+++ b/libs/backends/coreaudio/coreaudio_pcmio.cc
@@ -20,25 +20,60 @@
#include "coreaudio_pcmio.h"
#ifdef COREAUDIO_108
-static OSStatus hardwarePropertyChangeCallback(AudioObjectID inObjectID, UInt32 inNumberAddresses, const AudioObjectPropertyAddress inAddresses[], void* arg) {
+static OSStatus hw_changed_callback_ptr(AudioObjectID inObjectID, UInt32 inNumberAddresses, const AudioObjectPropertyAddress inAddresses[], void* arg) {
CoreAudioPCM * self = static_cast<CoreAudioPCM*>(arg);
- self->hwPropertyChange();
+ self->hw_changed_callback();
return noErr;
}
#else
-static OSStatus hardwarePropertyChangeCallback (AudioHardwarePropertyID inPropertyID, void* arg) {
+static OSStatus hw_changed_callback_ptr (AudioHardwarePropertyID inPropertyID, void* arg) {
if (inPropertyID == kAudioHardwarePropertyDevices) {
CoreAudioPCM * self = static_cast<CoreAudioPCM*>(arg);
- self->hwPropertyChange();
+ self->hw_changed_callback();
}
return noErr;
}
#endif
+#ifdef COREAUDIO_108
+static OSStatus xrun_callback_ptr(AudioObjectID inObjectID, UInt32 inNumberAddresses, const AudioObjectPropertyAddress inAddresses[], void* arg) {
+ CoreAudioPCM * self = static_cast<CoreAudioPCM*>(arg);
+ self->xrun_callback();
+ return noErr;
+}
+#else
+static OSStatus xrun_callback_ptr(
+ AudioDeviceID inDevice,
+ UInt32 inChannel,
+ Boolean isInput,
+ AudioDevicePropertyID inPropertyID,
+ void* inClientData)
+{
+ CoreAudioPCM * d = static_cast<CoreAudioPCM*> (inClientData);
+ d->xrun_callback();
+ return noErr;
+}
+#endif
+
+static OSStatus render_callback_ptr (
+ void* inRefCon,
+ AudioUnitRenderActionFlags* ioActionFlags,
+ const AudioTimeStamp* inTimeStamp,
+ UInt32 inBusNumber,
+ UInt32 inNumberFrames,
+ AudioBufferList* ioData)
+{
+ CoreAudioPCM * d = static_cast<CoreAudioPCM*> (inRefCon);
+ return d->render_callback(ioActionFlags, inTimeStamp, inBusNumber, inNumberFrames, ioData);
+}
+
+
CoreAudioPCM::CoreAudioPCM ()
: _auhal (0)
, _device_ids (0)
, _input_audio_buffer_list (0)
+ , _active_input (0)
+ , _active_output (0)
, _state (-1)
, _capture_channels (0)
, _playback_channels (0)
@@ -47,6 +82,7 @@ CoreAudioPCM::CoreAudioPCM ()
, _process_callback (0)
, _error_callback (0)
, _hw_changed_callback (0)
+ , _xrun_callback (0)
, _device_ins (0)
, _device_outs (0)
{
@@ -61,9 +97,9 @@ CoreAudioPCM::CoreAudioPCM ()
prop.mSelector = kAudioHardwarePropertyDevices;
prop.mScope = kAudioObjectPropertyScopeGlobal;
prop.mElement = 0;
- AudioObjectAddPropertyListener(kAudioObjectSystemObject, &prop, hardwarePropertyChangeCallback, this);
+ AudioObjectAddPropertyListener(kAudioObjectSystemObject, &prop, hw_changed_callback_ptr, this);
#else
- AudioHardwareAddPropertyListener (kAudioHardwarePropertyDevices, hardwarePropertyChangeCallback, this);
+ AudioHardwareAddPropertyListener (kAudioHardwarePropertyDevices, hw_changed_callback_ptr, this);
#endif
}
@@ -80,9 +116,9 @@ CoreAudioPCM::~CoreAudioPCM ()
prop.mSelector = kAudioHardwarePropertyDevices;
prop.mScope = kAudioObjectPropertyScopeGlobal;
prop.mElement = 0;
- AudioObjectRemovePropertyListener(kAudioObjectSystemObject, &prop, &hardwarePropertyChangeCallback, this);
+ AudioObjectRemovePropertyListener(kAudioObjectSystemObject, &prop, &hw_changed_callback_ptr, this);
#else
- AudioHardwareRemovePropertyListener(kAudioHardwarePropertyDevices, hardwarePropertyChangeCallback);
+ AudioHardwareRemovePropertyListener(kAudioHardwarePropertyDevices, hw_changed_callback_ptr);
#endif
free(_input_audio_buffer_list);
pthread_mutex_destroy (&_discovery_lock);
@@ -90,7 +126,8 @@ CoreAudioPCM::~CoreAudioPCM ()
void
-CoreAudioPCM::hwPropertyChange() {
+CoreAudioPCM::hw_changed_callback() {
+ printf("CHANGE..\n");
discover();
// TODO Filter events..
if (_hw_changed_callback) {
@@ -305,7 +342,7 @@ CoreAudioPCM::get_stream_latencies(uint32 device_id, bool input, std::vector<uin
return;
}
#ifndef NDEBUG
- printf("Stream %d latency: %d\n", i, stream_latency);
+ printf(" ^ Stream %d latency: %d\n", i, stream_latency);
#endif
latencies.push_back(stream_latency);
}
@@ -349,7 +386,8 @@ CoreAudioPCM::get_latency(uint32 device_id, bool input)
}
#ifndef NDEBUG
- printf("Base Latency systemic+safetyoffset = %d+%d\n", lat0, latS);
+ printf("%s Latency systemic+safetyoffset = %d + %d\n",
+ input ? "Input" : "Output", lat0, latS);
#endif
latency = lat0 + latS;
@@ -543,11 +581,40 @@ CoreAudioPCM::discover()
}
void
+CoreAudioPCM::xrun_callback ()
+{
+#ifndef NDEBUG
+ printf("Coreaudio XRUN\n");
+#endif
+ if (_xrun_callback) {
+ _xrun_callback(_xrun_arg);
+ }
+}
+
+void
CoreAudioPCM::pcm_stop ()
{
if (!_auhal) return;
AudioOutputUnitStop(_auhal);
+ if (_state == 0) {
+#ifdef COREAUDIO_108
+ AudioObjectPropertyAddress prop;
+ prop.mSelector = kAudioDeviceProcessorOverload;
+ prop.mScope = kAudioObjectPropertyScopeGlobal;
+ prop.mElement = 0;
+ if (_active_output > 0) {
+ AudioObjectRemovePropertyListener(_active_input, &prop, &xrun_callback_ptr, this);
+ }
+ if (_active_input > 0 && _active_output != _active_input) {
+ AudioObjectRemovePropertyListener(_active_output, &prop, &xrun_callback_ptr, this);
+ }
+#else
+ AudioDeviceRemovePropertyListener(_active_input, 0 , true, kAudioDeviceProcessorOverload, xrun_callback_ptr);
+ AudioDeviceRemovePropertyListener(_active_output, 0 , false, kAudioDeviceProcessorOverload, xrun_callback_ptr);
+#endif
+ }
+
AudioUnitUninitialize(_auhal);
#ifdef COREAUDIO_108
AudioComponentInstanceDispose(_auhal);
@@ -567,6 +634,7 @@ CoreAudioPCM::pcm_stop ()
_error_callback = 0;
_process_callback = 0;
+ _xrun_callback = 0;
}
#ifndef NDEBUG
@@ -585,20 +653,6 @@ static void PrintStreamDesc (AudioStreamBasicDescription *inDesc)
}
#endif
-static OSStatus render_callback_ptr (
- void* inRefCon,
- AudioUnitRenderActionFlags* ioActionFlags,
- const AudioTimeStamp* inTimeStamp,
- UInt32 inBusNumber,
- UInt32 inNumberFrames,
- AudioBufferList* ioData)
-{
- CoreAudioPCM * d = static_cast<CoreAudioPCM*> (inRefCon);
- return d->render_callback(ioActionFlags, inTimeStamp, inBusNumber, inNumberFrames, ioData);
-}
-
-
-
int
CoreAudioPCM::pcm_start (
uint32_t device_id_in, uint32_t device_id_out,
@@ -618,6 +672,7 @@ CoreAudioPCM::pcm_start (
_process_arg = process_arg;
_max_samples_per_period = samples_per_period;
_cur_samples_per_period = 0;
+ _active_input = _active_output = 0;
ComponentResult err;
UInt32 uint32val;
@@ -715,6 +770,7 @@ CoreAudioPCM::pcm_start (
#endif
if (err != noErr) { errorMsg="kAudioUnitProperty_StreamFormat Input"; goto error; }
+ /* read back stream descriptions */
UInt32 size;
size = sizeof(AudioStreamBasicDescription);
err = AudioUnitGetProperty(_auhal, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, AUHAL_INPUT_ELEMENT, &srcFormat, &size);
@@ -733,10 +789,32 @@ CoreAudioPCM::pcm_start (
PrintStreamDesc(&dstFormat);
#endif
+ /* prepare buffers for input */
_input_audio_buffer_list = (AudioBufferList*)malloc(sizeof(UInt32) + _capture_channels * sizeof(AudioBuffer));
assert(_input_audio_buffer_list);
if (!_input_audio_buffer_list) { errorMsg="Out of Memory."; goto error; }
+ _active_input = _device_ids[device_id_in];
+ _active_output = _device_ids[device_id_out];
+
+#ifdef COREAUDIO_108
+ AudioObjectPropertyAddress prop;
+ prop.mSelector = kAudioDeviceProcessorOverload;
+ prop.mScope = kAudioObjectPropertyScopeGlobal;
+ prop.mElement = 0;
+ AudioObjectAddPropertyListener(_active_output, &prop, xrun_callback_ptr, this);
+ if (err != noErr) { errorMsg="kAudioDeviceProcessorOverload, Output"; goto error; }
+ if (_active_input != _active_output) {
+ AudioObjectAddPropertyListener(_active_input, &prop, xrun_callback_ptr, this);
+ if (err != noErr) { errorMsg="kAudioDeviceProcessorOverload, Input"; goto error; }
+ }
+#else
+ err = AudioDeviceAddPropertyListener(_device_ids[device_id_out], 0 , false, kAudioDeviceProcessorOverload, xrun_callback_ptr, this);
+ if (err != noErr) { errorMsg="kAudioDeviceProcessorOverload, Output"; goto error; }
+ err = AudioDeviceAddPropertyListener(_device_ids[device_id_in], 0 , true, kAudioDeviceProcessorOverload, xrun_callback_ptr, this);
+ if (err != noErr) { errorMsg="kAudioDeviceProcessorOverload, Input"; goto error; }
+#endif
+
// Setup callbacks
AURenderCallbackStruct renderCallback;
memset (&renderCallback, 0, sizeof (renderCallback));
@@ -748,6 +826,7 @@ CoreAudioPCM::pcm_start (
&renderCallback, sizeof (renderCallback));
if (err != noErr) { errorMsg="kAudioUnitProperty_SetRenderCallback"; goto error; }
+ /* setup complete, now get going.. */
if (AudioOutputUnitStart(_auhal) == noErr) {
_input_names.clear();
_output_names.clear();
@@ -762,6 +841,7 @@ error:
fprintf(stderr, "CoreaudioPCM Error: %c%c%c%c %s\n", rv[0], rv[1], rv[2], rv[3], errorMsg.c_str());
pcm_stop();
_state = -3;
+ _active_input = _active_output = 0;
return -1;
}
@@ -810,7 +890,7 @@ CoreAudioPCM::cache_port_names(uint32 device_id, bool input)
&name);
#endif
}
-
+
bool decoded = false;
char* cstr_name = 0;
if (err == kAudioHardwareNoError) {
@@ -820,19 +900,14 @@ CoreAudioPCM::cache_port_names(uint32 device_id, bool input)
decoded = CFStringGetCString(name, cstr_name, maxSize, kCFStringEncodingUTF8);
}
- ss << (c + 1) << " - ";
+ ss << (c + 1);
if (cstr_name && decoded && (0 != std::strlen(cstr_name) ) ) {
- ss << cstr_name;
- } else {
- if (input) {
- ss << "Input " << (c + 1);
- } else {
- ss << "Output " << (c + 1);
- }
+ ss << " - " << cstr_name;
}
-
+#if 0
printf("%s %d Name: %s\n", input ? "Input" : "Output", c+1, ss.str().c_str());
+#endif
if (input) {
_input_names.push_back (ss.str());