Bug 1384053 - Update cubeb from upstream to 09aeb59. r=kinetik

MozReview-Commit-ID: KQRqIGv021z

--HG--
extra : rebase_source : e024379549aa71c831a56dc91b41389838970550
This commit is contained in:
Alex Chronopoulos 2017-07-25 18:00:35 +03:00
Родитель c1d621cbd6
Коммит 0335e95f16
2 изменённых файлов: 199 добавлений и 221 удалений

Просмотреть файл

@ -5,4 +5,4 @@ Makefile.in build files for the Mozilla build system.
The cubeb git repository is: git://github.com/kinetiknz/cubeb.git
The git commit ID used was a329c6a4184de3ccedb264cf2c3b0903fc506b94 (2017-07-14 15:35:51 +0300)
The git commit ID used was 09aeb59259487a2fbeeca1824f1f68f55b6787f4 (2017-07-22 09:54:44 +1200)

Просмотреть файл

@ -107,6 +107,21 @@ to_string(io_side side)
}
}
typedef uint32_t device_flags_value;
enum device_flags {
DEV_UKNOWN = 0x00, /* Unkown */
DEV_INPUT = 0x01, /* Record device like mic */
DEV_OUTPUT = 0x02, /* Playback device like speakers */
DEV_SYSTEM_DEFAULT = 0x04, /* System default device */
DEV_SELECTED_DEFAULT = 0x08, /* User selected to use the system default device */
};
struct device_info {
AudioDeviceID id = kAudioObjectUnknown;
device_flags_value flags = DEV_UKNOWN;
};
struct cubeb_stream {
explicit cubeb_stream(cubeb * context);
@ -118,9 +133,8 @@ struct cubeb_stream {
/* Stream creation parameters */
cubeb_stream_params input_stream_params = { CUBEB_SAMPLE_FLOAT32NE, 0, 0, CUBEB_LAYOUT_UNDEFINED };
cubeb_stream_params output_stream_params = { CUBEB_SAMPLE_FLOAT32NE, 0, 0, CUBEB_LAYOUT_UNDEFINED };
bool is_default_input;
AudioDeviceID input_device = 0;
AudioDeviceID output_device = 0;
device_info input_device;
device_info output_device;
/* User pointer of data_callback */
void * user_ptr = nullptr;
/* Format descriptions */
@ -554,75 +568,64 @@ audiounit_get_backend_id(cubeb * /* ctx */)
}
#if !TARGET_OS_IPHONE
static int
audiounit_get_output_device_id(AudioDeviceID * device_id)
{
UInt32 size;
OSStatus r;
AudioObjectPropertyAddress output_device_address = {
kAudioHardwarePropertyDefaultOutputDevice,
kAudioObjectPropertyScopeGlobal,
kAudioObjectPropertyElementMaster
};
size = sizeof(*device_id);
r = AudioObjectGetPropertyData(kAudioObjectSystemObject,
&output_device_address,
0,
NULL,
&size,
device_id);
if (r != noErr) {
LOG("output_device_id rv=%d", r);
return CUBEB_ERROR;
}
return CUBEB_OK;
}
static int
audiounit_get_input_device_id(AudioDeviceID * device_id)
{
UInt32 size;
OSStatus r;
AudioObjectPropertyAddress input_device_address = {
kAudioHardwarePropertyDefaultInputDevice,
kAudioObjectPropertyScopeGlobal,
kAudioObjectPropertyElementMaster
};
size = sizeof(*device_id);
r = AudioObjectGetPropertyData(kAudioObjectSystemObject,
&input_device_address,
0,
NULL,
&size,
device_id);
if (r != noErr) {
return CUBEB_ERROR;
}
return CUBEB_OK;
}
static int audiounit_stream_get_volume(cubeb_stream * stm, float * volume);
static int audiounit_stream_set_volume(cubeb_stream * stm, float volume);
static int audiounit_uninstall_device_changed_callback(cubeb_stream * stm);
static AudioObjectID audiounit_get_default_device_id(cubeb_device_type type);
static void
audiounit_set_device_info(cubeb_stream * stm, AudioDeviceID id, io_side side)
{
assert(stm);
device_info * info = nullptr;
cubeb_device_type type = CUBEB_DEVICE_TYPE_UNKNOWN;
if (side == INPUT) {
info = &stm->input_device;
type = CUBEB_DEVICE_TYPE_INPUT;
} else if (side == OUTPUT) {
info = &stm->output_device;
type = CUBEB_DEVICE_TYPE_OUTPUT;
}
memset(info, 0, sizeof(device_info));
if (side == INPUT) {
info->flags |= DEV_INPUT;
} else if (side == OUTPUT) {
info->flags |= DEV_OUTPUT;
}
AudioDeviceID default_device_id = audiounit_get_default_device_id(type);
if (id == kAudioObjectUnknown) {
info->id = default_device_id;
info->flags |= DEV_SELECTED_DEFAULT;
}
if (info->id == default_device_id) {
info->flags |= DEV_SYSTEM_DEFAULT;
}
assert(info->id);
assert(info->flags & DEV_INPUT && !(info->flags & DEV_OUTPUT) ||
!(info->flags & DEV_INPUT) && info->flags & DEV_OUTPUT);
}
static int
audiounit_reinit_stream(cubeb_stream * stm)
audiounit_reinit_stream(cubeb_stream * stm, device_flags_value flags)
{
auto_lock context_lock(stm->context->mutex);
assert(stm->input_unit || stm->output_unit);
assert((flags & DEV_INPUT && stm->input_unit) ||
(flags & DEV_OUTPUT && stm->output_unit));
if (!stm->shutdown) {
audiounit_stream_stop_internal(stm);
}
int r = audiounit_uninstall_device_changed_callback(stm);
if (r != CUBEB_OK) {
LOG("(%p) Could not uninstall the device changed callback", stm);
LOG("(%p) Could not uninstall all device change listeners.", stm);
}
{
@ -635,6 +638,17 @@ audiounit_reinit_stream(cubeb_stream * stm)
audiounit_close_stream(stm);
/* Reinit occurs in 2 cases. When the device is not alive any more and when the
* default system device change. In both cases cubeb switch on the new default
* device. This is considered the most expected behavior for the user. */
if (flags & DEV_INPUT) {
audiounit_set_device_info(stm, 0, INPUT);
}
/* Always use the default output on reinit. This is not correct in every case
* but it is sufficient for Firefox and prevent reinit from reporting failures.
* It will change soon when reinit mechanism will be updated. */
audiounit_set_device_info(stm, 0, OUTPUT);
if (audiounit_setup_stream(stm) != CUBEB_OK) {
LOG("(%p) Stream reinit failed.", stm);
return CUBEB_ERROR;
@ -663,6 +677,7 @@ audiounit_property_listener_callback(AudioObjectID /* id */, UInt32 address_coun
{
cubeb_stream * stm = (cubeb_stream*) user;
stm->switching_device = true;
device_flags_value switch_side = DEV_UKNOWN;
LOG("(%p) Audio device changed, %u events.", stm, (unsigned int) address_count);
for (UInt32 i = 0; i < address_count; i++) {
@ -670,25 +685,25 @@ audiounit_property_listener_callback(AudioObjectID /* id */, UInt32 address_coun
case kAudioHardwarePropertyDefaultOutputDevice: {
LOG("Event[%u] - mSelector == kAudioHardwarePropertyDefaultOutputDevice", (unsigned int) i);
// Allow restart to choose the new default
stm->output_device = 0;
switch_side |= DEV_OUTPUT;
}
break;
case kAudioHardwarePropertyDefaultInputDevice: {
LOG("Event[%u] - mSelector == kAudioHardwarePropertyDefaultInputDevice", (unsigned int) i);
// Allow restart to choose the new default
stm->input_device = 0;
switch_side |= DEV_INPUT;
}
break;
case kAudioDevicePropertyDeviceIsAlive: {
LOG("Event[%u] - mSelector == kAudioDevicePropertyDeviceIsAlive", (unsigned int) i);
// If this is the default input device ignore the event,
// kAudioHardwarePropertyDefaultInputDevice will take care of the switch
if (stm->is_default_input) {
if (stm->input_device.flags & DEV_SYSTEM_DEFAULT) {
LOG("It's the default input device, ignore the event");
return noErr;
}
// Allow restart to choose the new default. Event register only for input.
stm->input_device = 0;
switch_side |= DEV_INPUT;
}
break;
case kAudioDevicePropertyDataSource: {
@ -720,7 +735,7 @@ audiounit_property_listener_callback(AudioObjectID /* id */, UInt32 address_coun
// Use a new thread, through the queue, to avoid deadlock when calling
// Get/SetProperties method from inside notify callback
dispatch_async(stm->context->serial_queue, ^() {
if (audiounit_reinit_stream(stm) != CUBEB_OK) {
if (audiounit_reinit_stream(stm, switch_side) != CUBEB_OK) {
stm->state_callback(stm, stm->user_ptr, CUBEB_STATE_STOPPED);
LOG("(%p) Could not reopen the stream after switching.", stm);
}
@ -758,66 +773,43 @@ audiounit_remove_listener(cubeb_stream * stm, AudioDeviceID id,
return AudioObjectRemovePropertyListener(id, &address, listener, stm);
}
static AudioObjectID audiounit_get_default_device_id(cubeb_device_type type);
static AudioObjectID
audiounit_get_input_device_id(cubeb_stream * stm)
{
AudioObjectID input_dev = stm->input_device ? stm->input_device :
audiounit_get_default_device_id(CUBEB_DEVICE_TYPE_INPUT);
assert(input_dev);
return input_dev;
}
static int
audiounit_install_device_changed_callback(cubeb_stream * stm)
{
OSStatus r;
OSStatus rv;
int r = CUBEB_OK;
if (stm->output_unit) {
/* This event will notify us when the data source on the same device changes,
* for example when the user plugs in a normal (non-usb) headset in the
* headphone jack. */
AudioDeviceID output_dev_id;
r = audiounit_get_output_device_id(&output_dev_id);
if (r != noErr) {
return CUBEB_ERROR;
}
r = audiounit_add_listener(stm, output_dev_id, kAudioDevicePropertyDataSource,
rv = audiounit_add_listener(stm, stm->output_device.id, kAudioDevicePropertyDataSource,
kAudioDevicePropertyScopeOutput, &audiounit_property_listener_callback);
if (r != noErr) {
LOG("AudioObjectAddPropertyListener/output/kAudioDevicePropertyDataSource rv=%d", r);
return CUBEB_ERROR;
if (rv != noErr) {
LOG("AudioObjectAddPropertyListener/output/kAudioDevicePropertyDataSource rv=%d, device id=%d", rv, stm->output_device.id);
r = CUBEB_ERROR;
}
}
if (stm->input_unit) {
/* This event will notify us when the data source on the input device changes. */
AudioDeviceID input_dev_id;
r = audiounit_get_input_device_id(&input_dev_id);
if (r != noErr) {
return CUBEB_ERROR;
}
r = audiounit_add_listener(stm, input_dev_id, kAudioDevicePropertyDataSource,
rv = audiounit_add_listener(stm, stm->input_device.id, kAudioDevicePropertyDataSource,
kAudioDevicePropertyScopeInput, &audiounit_property_listener_callback);
if (r != noErr) {
LOG("AudioObjectAddPropertyListener/input/kAudioDevicePropertyDataSource rv=%d", r);
return CUBEB_ERROR;
if (rv != noErr) {
LOG("AudioObjectAddPropertyListener/input/kAudioDevicePropertyDataSource rv=%d, device id=%d", rv, stm->input_device.id);
r = CUBEB_ERROR;
}
/* Event to notify when the input is going away. */
AudioDeviceID dev = audiounit_get_input_device_id(stm);
r = audiounit_add_listener(stm, dev, kAudioDevicePropertyDeviceIsAlive,
rv = audiounit_add_listener(stm, stm->input_device.id, kAudioDevicePropertyDeviceIsAlive,
kAudioObjectPropertyScopeGlobal, &audiounit_property_listener_callback);
if (r != noErr) {
LOG("AudioObjectAddPropertyListener/input/kAudioDevicePropertyDeviceIsAlive rv=%d", r);
return CUBEB_ERROR;
if (rv != noErr) {
LOG("AudioObjectAddPropertyListener/input/kAudioDevicePropertyDeviceIsAlive rv=%d, device id =%d", rv, stm->input_device.id);
r = CUBEB_ERROR;
}
}
return CUBEB_OK;
return r;
}
static int
@ -854,44 +846,35 @@ audiounit_install_system_changed_callback(cubeb_stream * stm)
static int
audiounit_uninstall_device_changed_callback(cubeb_stream * stm)
{
OSStatus r;
OSStatus rv;
// Failing to uninstall listeners is not a fatal error.
int r = CUBEB_OK;
if (stm->output_unit) {
AudioDeviceID output_dev_id;
r = audiounit_get_output_device_id(&output_dev_id);
if (r != noErr) {
return CUBEB_ERROR;
}
r = audiounit_remove_listener(stm, output_dev_id, kAudioDevicePropertyDataSource,
rv = audiounit_remove_listener(stm, stm->output_device.id, kAudioDevicePropertyDataSource,
kAudioDevicePropertyScopeOutput, &audiounit_property_listener_callback);
if (r != noErr) {
return CUBEB_ERROR;
if (rv != noErr) {
LOG("AudioObjectRemovePropertyListener/output/kAudioDevicePropertyDataSource rv=%d, device id=%d", rv, stm->output_device.id);
r = CUBEB_ERROR;
}
}
if (stm->input_unit) {
AudioDeviceID input_dev_id;
r = audiounit_get_input_device_id(&input_dev_id);
if (r != noErr) {
return CUBEB_ERROR;
}
r = audiounit_remove_listener(stm, input_dev_id, kAudioDevicePropertyDataSource,
rv = audiounit_remove_listener(stm, stm->input_device.id, kAudioDevicePropertyDataSource,
kAudioDevicePropertyScopeInput, &audiounit_property_listener_callback);
if (r != noErr) {
return CUBEB_ERROR;
if (rv != noErr) {
LOG("AudioObjectRemovePropertyListener/input/kAudioDevicePropertyDataSource rv=%d, device id=%d", rv, stm->input_device.id);
r = CUBEB_ERROR;
}
AudioDeviceID dev = audiounit_get_input_device_id(stm);
r = audiounit_remove_listener(stm, dev, kAudioDevicePropertyDeviceIsAlive,
rv = audiounit_remove_listener(stm, stm->input_device.id, kAudioDevicePropertyDeviceIsAlive,
kAudioObjectPropertyScopeGlobal, &audiounit_property_listener_callback);
if (r != noErr) {
LOG("AudioObjectRemovePropertyListener/input/kAudioDevicePropertyDeviceIsAlive rv=%d", r);
return CUBEB_ERROR;
if (rv != noErr) {
LOG("AudioObjectRemovePropertyListener/input/kAudioDevicePropertyDeviceIsAlive rv=%d, device id=%d", rv, stm->input_device.id);
r = CUBEB_ERROR;
}
}
return CUBEB_OK;
return r;
}
static int
@ -930,7 +913,8 @@ audiounit_get_acceptable_latency_range(AudioValueRange * latency_range)
kAudioObjectPropertyElementMaster
};
if (audiounit_get_output_device_id(&output_device_id) != CUBEB_OK) {
output_device_id = audiounit_get_default_device_id(CUBEB_DEVICE_TYPE_OUTPUT);
if (output_device_id == kAudioObjectUnknown) {
LOG("Could not get default output device id.");
return CUBEB_ERROR;
}
@ -995,7 +979,8 @@ audiounit_get_max_channel_count(cubeb * ctx, uint32_t * max_channels)
assert(ctx && max_channels);
if (audiounit_get_output_device_id(&output_device_id) != CUBEB_OK) {
output_device_id = audiounit_get_default_device_id(CUBEB_DEVICE_TYPE_OUTPUT);
if (output_device_id == kAudioObjectUnknown) {
return CUBEB_ERROR;
}
@ -1056,7 +1041,8 @@ audiounit_get_preferred_sample_rate(cubeb * /* ctx */, uint32_t * rate)
kAudioObjectPropertyElementMaster
};
if (audiounit_get_output_device_id(&output_device_id) != CUBEB_OK) {
output_device_id = audiounit_get_default_device_id(CUBEB_DEVICE_TYPE_OUTPUT);
if (output_device_id == kAudioObjectUnknown) {
return CUBEB_ERROR;
}
@ -1143,7 +1129,8 @@ audiounit_get_preferred_channel_layout()
UInt32 size = 0;
AudioDeviceID id;
if (audiounit_get_output_device_id(&id) != CUBEB_OK) {
id = audiounit_get_default_device_id(CUBEB_DEVICE_TYPE_OUTPUT);
if (id == kAudioObjectUnknown) {
return CUBEB_LAYOUT_UNDEFINED;
}
@ -1165,7 +1152,7 @@ audiounit_get_preferred_channel_layout()
return audiounit_convert_channel_layout(layout.get());
}
static int audiounit_create_unit(AudioUnit * unit, io_side side, AudioDeviceID device);
static int audiounit_create_unit(AudioUnit * unit, device_info * device);
static int
audiounit_get_preferred_channel_layout(cubeb * ctx, cubeb_channel_layout * layout)
@ -1189,8 +1176,13 @@ audiounit_get_preferred_channel_layout(cubeb * ctx, cubeb_channel_layout * layou
// If there is no existed stream, then we create a default ouput unit and
// use it to get the current used channel layout.
AudioUnit output_unit = nullptr;
audiounit_create_unit(&output_unit, OUTPUT, 0);
*layout = audiounit_get_current_channel_layout(output_unit);
device_info default_out_device;
default_out_device.id = audiounit_get_default_device_id(CUBEB_DEVICE_TYPE_OUTPUT);
default_out_device.flags = (DEV_OUTPUT | DEV_SYSTEM_DEFAULT);
if (default_out_device.id != kAudioObjectUnknown) {
audiounit_create_unit(&output_unit, &default_out_device);
*layout = audiounit_get_current_channel_layout(output_unit);
}
}
if (*layout == CUBEB_LAYOUT_UNDEFINED) {
@ -1639,7 +1631,7 @@ audiounit_activate_clock_drift_compensation(const AudioDeviceID aggregate_device
return CUBEB_OK;
}
static int audiounit_destroy_aggregate_device(AudioObjectID plugin_id, AudioDeviceID aggregate_device_id);
static int audiounit_destroy_aggregate_device(AudioObjectID plugin_id, AudioDeviceID * aggregate_device_id);
/*
* Aggregate Device is a virtual audio interface which utilizes inputs and outputs
@ -1666,30 +1658,28 @@ audiounit_create_aggregate_device(cubeb_stream * stm)
int r = audiounit_create_blank_aggregate_device(&stm->plugin_id, &stm->aggregate_device_id);
if (r != CUBEB_OK) {
LOG("(%p) Failed to create blank aggregate device", stm);
audiounit_destroy_aggregate_device(stm->plugin_id, stm->aggregate_device_id);
audiounit_destroy_aggregate_device(stm->plugin_id, &stm->aggregate_device_id);
return CUBEB_ERROR;
}
AudioDeviceID input_device_id = audiounit_get_input_device_id(stm);
AudioDeviceID output_device_id = audiounit_get_default_device_id(CUBEB_DEVICE_TYPE_OUTPUT);
r = audiounit_set_aggregate_sub_device_list(stm->aggregate_device_id, input_device_id, output_device_id);
r = audiounit_set_aggregate_sub_device_list(stm->aggregate_device_id, stm->input_device.id, stm->output_device.id);
if (r != CUBEB_OK) {
LOG("(%p) Failed to set aggregate sub-device list", stm);
audiounit_destroy_aggregate_device(stm->plugin_id, stm->aggregate_device_id);
audiounit_destroy_aggregate_device(stm->plugin_id, &stm->aggregate_device_id);
return CUBEB_ERROR;
}
r = audiounit_set_master_aggregate_device(stm->aggregate_device_id);
if (r != CUBEB_OK) {
LOG("(%p) Failed to set master sub-device for aggregate device", stm);
audiounit_destroy_aggregate_device(stm->plugin_id, stm->aggregate_device_id);
audiounit_destroy_aggregate_device(stm->plugin_id, &stm->aggregate_device_id);
return CUBEB_ERROR;
}
r = audiounit_activate_clock_drift_compensation(stm->aggregate_device_id);
if (r != CUBEB_OK) {
LOG("(%p) Failed to activate clock drift compensation for aggregate device", stm);
audiounit_destroy_aggregate_device(stm->plugin_id, stm->aggregate_device_id);
audiounit_destroy_aggregate_device(stm->plugin_id, &stm->aggregate_device_id);
return CUBEB_ERROR;
}
@ -1697,7 +1687,7 @@ audiounit_create_aggregate_device(cubeb_stream * stm)
}
static int
audiounit_destroy_aggregate_device(AudioObjectID plugin_id, AudioDeviceID aggregate_device_id)
audiounit_destroy_aggregate_device(AudioObjectID plugin_id, AudioDeviceID * aggregate_device_id)
{
AudioObjectPropertyAddress destroy_aggregate_device_addr = { kAudioPlugInDestroyAggregateDevice,
kAudioObjectPropertyScopeGlobal,
@ -1718,17 +1708,19 @@ audiounit_destroy_aggregate_device(AudioObjectID plugin_id, AudioDeviceID aggreg
0,
NULL,
&size,
&aggregate_device_id);
aggregate_device_id);
if (rv != noErr) {
LOG("AudioObjectGetPropertyData/kAudioPlugInDestroyAggregateDevice, rv=%d", rv);
return CUBEB_ERROR;
}
LOG("Destroyed aggregate device %d", *aggregate_device_id);
*aggregate_device_id = 0;
return CUBEB_OK;
}
static int
audiounit_new_unit_instance(AudioUnit * unit, io_side side, AudioDeviceID device)
audiounit_new_unit_instance(AudioUnit * unit, device_info * device)
{
AudioComponentDescription desc;
AudioComponent comp;
@ -1736,15 +1728,14 @@ audiounit_new_unit_instance(AudioUnit * unit, io_side side, AudioDeviceID device
desc.componentType = kAudioUnitType_Output;
#if TARGET_OS_IPHONE
bool use_default_output = false;
desc.componentSubType = kAudioUnitSubType_RemoteIO;
#else
// Use the DefaultOutputUnit for output when no device is specified
// so we retain automatic output device switching when the default
// changes. Once we have complete support for device notifications
// and switching, we can use the AUHAL for everything.
bool use_default_output = device == 0 && (side == OUTPUT);
if (use_default_output) {
if ((device->flags & DEV_SYSTEM_DEFAULT)
&& (device->flags & DEV_OUTPUT)) {
desc.componentSubType = kAudioUnitSubType_DefaultOutput;
} else {
desc.componentSubType = kAudioUnitSubType_HALOutput;
@ -1790,71 +1781,60 @@ audiounit_enable_unit_scope(AudioUnit * unit, io_side side, enable_state state)
}
static int
audiounit_create_unit(AudioUnit * unit, io_side side, AudioDeviceID device)
audiounit_create_unit(AudioUnit * unit, device_info * device)
{
AudioDeviceID devid;
assert(*unit == nullptr);
assert(device);
OSStatus rv;
int r;
assert(*unit == nullptr);
r = audiounit_new_unit_instance(unit, side, device);
r = audiounit_new_unit_instance(unit, device);
if (r != CUBEB_OK) {
return r;
}
assert(*unit);
#if TARGET_OS_IPHONE
bool use_default_output = false;
#else
bool use_default_output = device == 0 && (side == OUTPUT);
#endif
if ((device->flags & DEV_SYSTEM_DEFAULT)
&& (device->flags & DEV_OUTPUT)) {
return CUBEB_OK;
}
if (!use_default_output) {
switch (side) {
case INPUT:
r = audiounit_enable_unit_scope(unit, INPUT, ENABLE);
if (r != CUBEB_OK) {
LOG("Failed to enable audiounit input scope ");
return r;
}
r = audiounit_enable_unit_scope(unit, OUTPUT, DISABLE);
if (r != CUBEB_OK) {
LOG("Failed to disable audiounit output scope ");
return r;
}
break;
case OUTPUT:
r = audiounit_enable_unit_scope(unit, OUTPUT, ENABLE);
if (r != CUBEB_OK) {
LOG("Failed to enable audiounit output scope ");
return r;
}
r = audiounit_enable_unit_scope(unit, INPUT, DISABLE);
if (r != CUBEB_OK) {
LOG("Failed to disable audiounit input scope ");
return r;
}
break;
default:
assert(false);
}
if (device == 0) {
assert(side == INPUT);
devid = audiounit_get_default_device_id(CUBEB_DEVICE_TYPE_INPUT);
} else {
devid = device;
if (device->flags & DEV_INPUT) {
r = audiounit_enable_unit_scope(unit, INPUT, ENABLE);
if (r != CUBEB_OK) {
LOG("Failed to enable audiounit input scope ");
return r;
}
r = audiounit_enable_unit_scope(unit, OUTPUT, DISABLE);
if (r != CUBEB_OK) {
LOG("Failed to disable audiounit output scope ");
return r;
}
} else if (device->flags & DEV_OUTPUT) {
r = audiounit_enable_unit_scope(unit, OUTPUT, ENABLE);
if (r != CUBEB_OK) {
LOG("Failed to enable audiounit output scope ");
return r;
}
r = audiounit_enable_unit_scope(unit, INPUT, DISABLE);
if (r != CUBEB_OK) {
LOG("Failed to disable audiounit input scope ");
return r;
}
} else {
assert(false);
}
rv = AudioUnitSetProperty(*unit,
kAudioOutputUnitProperty_CurrentDevice,
kAudioUnitScope_Global,
0,
&devid, sizeof(AudioDeviceID));
if (rv != noErr) {
LOG("AudioUnitSetProperty/kAudioOutputUnitProperty_CurrentDevice rv=%d", rv);
return CUBEB_ERROR;
}
rv = AudioUnitSetProperty(*unit,
kAudioOutputUnitProperty_CurrentDevice,
kAudioUnitScope_Global,
0,
&device->id, sizeof(AudioDeviceID));
if (rv != noErr) {
LOG("AudioUnitSetProperty/kAudioOutputUnitProperty_CurrentDevice rv=%d", rv);
return CUBEB_ERROR;
}
return CUBEB_OK;
@ -2278,8 +2258,9 @@ audiounit_setup_stream(cubeb_stream * stm)
int r = 0;
AudioDeviceID in_dev = stm->input_device;
AudioDeviceID out_dev = stm->output_device;
device_info in_dev_info = stm->input_device;
device_info out_dev_info = stm->output_device;
if (has_input(stm) && has_output(stm)) {
r = audiounit_create_aggregate_device(stm);
if (r != CUBEB_OK) {
@ -2291,14 +2272,14 @@ audiounit_setup_stream(cubeb_stream * stm)
// it after a couple of weeks.
return r;
} else {
in_dev = out_dev = stm->aggregate_device_id;
in_dev_info.id = out_dev_info.id = stm->aggregate_device_id;
in_dev_info.flags = DEV_INPUT;
out_dev_info.flags = DEV_OUTPUT;
}
}
if (has_input(stm)) {
r = audiounit_create_unit(&stm->input_unit,
INPUT,
in_dev);
r = audiounit_create_unit(&stm->input_unit, &in_dev_info);
if (r != CUBEB_OK) {
LOG("(%p) AudioUnit creation for input failed.", stm);
return r;
@ -2306,9 +2287,7 @@ audiounit_setup_stream(cubeb_stream * stm)
}
if (has_output(stm)) {
r = audiounit_create_unit(&stm->output_unit,
OUTPUT,
out_dev);
r = audiounit_create_unit(&stm->output_unit, &out_dev_info);
if (r != CUBEB_OK) {
LOG("(%p) AudioUnit creation for output failed.", stm);
return r;
@ -2446,8 +2425,7 @@ audiounit_setup_stream(cubeb_stream * stm)
r = audiounit_install_device_changed_callback(stm);
if (r != CUBEB_OK) {
LOG("(%p) Could not install the device change callback.", stm);
return r;
LOG("(%p) Could not install all device change callback.", stm);
}
@ -2497,13 +2475,11 @@ audiounit_stream_init(cubeb * context,
stm->latency_frames = latency_frames;
if (input_stream_params) {
stm->input_stream_params = *input_stream_params;
stm->input_device = reinterpret_cast<uintptr_t>(input_device);
stm->is_default_input = stm->input_device == 0 ||
(audiounit_get_default_device_id(CUBEB_DEVICE_TYPE_INPUT) == stm->input_device);
audiounit_set_device_info(stm.get(), reinterpret_cast<uintptr_t>(input_device), INPUT);
}
if (output_stream_params) {
stm->output_stream_params = *output_stream_params;
stm->output_device = reinterpret_cast<uintptr_t>(output_device);
audiounit_set_device_info(stm.get(), reinterpret_cast<uintptr_t>(output_device), OUTPUT);
}
auto_lock context_lock(context->mutex);
@ -2555,7 +2531,7 @@ audiounit_close_stream(cubeb_stream *stm)
stm->mixer.reset();
if (stm->aggregate_device_id) {
audiounit_destroy_aggregate_device(stm->plugin_id, stm->aggregate_device_id);
audiounit_destroy_aggregate_device(stm->plugin_id, &stm->aggregate_device_id);
stm->aggregate_device_id = 0;
}
}
@ -2572,7 +2548,7 @@ audiounit_stream_destroy(cubeb_stream * stm)
r = audiounit_uninstall_device_changed_callback(stm);
if (r != CUBEB_OK) {
LOG("(%p) Could not uninstall the device changed callback", stm);
LOG("(%p) Could not uninstall all device change listeners", stm);
}
auto_lock context_lock(stm->context->mutex);
@ -2682,8 +2658,8 @@ audiounit_stream_get_latency(cubeb_stream * stm, uint32_t * latency)
kAudioObjectPropertyElementMaster
};
r = audiounit_get_output_device_id(&output_device_id);
if (r != noErr) {
output_device_id = audiounit_get_default_device_id(CUBEB_DEVICE_TYPE_OUTPUT);
if (output_device_id == kAudioObjectUnknown) {
return CUBEB_ERROR;
}
@ -2806,7 +2782,8 @@ int audiounit_stream_get_current_device(cubeb_stream * stm,
*device = NULL;
if (audiounit_get_output_device_id(&output_device_id) != CUBEB_OK) {
output_device_id = audiounit_get_default_device_id(CUBEB_DEVICE_TYPE_OUTPUT);
if (output_device_id == kAudioObjectUnknown) {
return CUBEB_ERROR;
}
@ -2840,7 +2817,8 @@ int audiounit_stream_get_current_device(cubeb_stream * stm,
memcpy((*device)->output_name, strdata, size);
(*device)->output_name[size] = '\0';
if (audiounit_get_input_device_id(&input_device_id) != CUBEB_OK) {
input_device_id = audiounit_get_default_device_id(CUBEB_DEVICE_TYPE_INPUT);
if (input_device_id == kAudioObjectUnknown) {
return CUBEB_ERROR;
}