gecko-dev/media/libcubeb/0003-audiounit-ios-compile-fixes.patch
Andreas Pehrson c6c23802dc Bug 1895787 - Update libcubeb patches. r=cubeb-reviewers,padenot
Unbitrot local libcubeb patches after update.

Differential Revision: https://phabricator.services.mozilla.com/D211045
2024-05-22 20:43:23 +00:00

1416 lines
45 KiB
Diff
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

diff --git a/src/cubeb_audiounit.cpp b/src/cubeb_audiounit.cpp
--- a/src/cubeb_audiounit.cpp
+++ b/src/cubeb_audiounit.cpp
@@ -36,16 +36,25 @@
#include <vector>
using namespace std;
#if MAC_OS_X_VERSION_MIN_REQUIRED < 101000
typedef UInt32 AudioFormatFlags;
#endif
+#if TARGET_OS_IPHONE
+typedef UInt32 AudioDeviceID;
+typedef UInt32 AudioObjectID;
+const UInt32 kAudioObjectUnknown = 0;
+
+#define AudioGetCurrentHostTime mach_absolute_time
+
+#endif
+
#define AU_OUT_BUS 0
#define AU_IN_BUS 1
const char * DISPATCH_QUEUE_LABEL = "org.mozilla.cubeb";
const char * PRIVATE_AGGREGATE_DEVICE_NAME = "CubebAggregateDevice";
#ifdef ALOGV
#undef ALOGV
@@ -60,45 +69,47 @@ const char * PRIVATE_AGGREGATE_DEVICE_NA
#undef ALOG
#endif
#define ALOG(msg, ...) \
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), \
^{ \
LOG(msg, ##__VA_ARGS__); \
})
+#if !TARGET_OS_IPHONE
/* Testing empirically, some headsets report a minimal latency that is very
* low, but this does not work in practice. Lie and say the minimum is 256
* frames. */
const uint32_t SAFE_MIN_LATENCY_FRAMES = 128;
const uint32_t SAFE_MAX_LATENCY_FRAMES = 512;
const AudioObjectPropertyAddress DEFAULT_INPUT_DEVICE_PROPERTY_ADDRESS = {
kAudioHardwarePropertyDefaultInputDevice, kAudioObjectPropertyScopeGlobal,
- kAudioObjectPropertyElementMaster};
+ kAudioObjectPropertyElementMain};
const AudioObjectPropertyAddress DEFAULT_OUTPUT_DEVICE_PROPERTY_ADDRESS = {
kAudioHardwarePropertyDefaultOutputDevice, kAudioObjectPropertyScopeGlobal,
- kAudioObjectPropertyElementMaster};
+ kAudioObjectPropertyElementMain};
const AudioObjectPropertyAddress DEVICE_IS_ALIVE_PROPERTY_ADDRESS = {
kAudioDevicePropertyDeviceIsAlive, kAudioObjectPropertyScopeGlobal,
- kAudioObjectPropertyElementMaster};
+ kAudioObjectPropertyElementMain};
const AudioObjectPropertyAddress DEVICES_PROPERTY_ADDRESS = {
kAudioHardwarePropertyDevices, kAudioObjectPropertyScopeGlobal,
- kAudioObjectPropertyElementMaster};
+ kAudioObjectPropertyElementMain};
const AudioObjectPropertyAddress INPUT_DATA_SOURCE_PROPERTY_ADDRESS = {
kAudioDevicePropertyDataSource, kAudioDevicePropertyScopeInput,
- kAudioObjectPropertyElementMaster};
+ kAudioObjectPropertyElementMain};
const AudioObjectPropertyAddress OUTPUT_DATA_SOURCE_PROPERTY_ADDRESS = {
kAudioDevicePropertyDataSource, kAudioDevicePropertyScopeOutput,
- kAudioObjectPropertyElementMaster};
+ kAudioObjectPropertyElementMain};
+#endif
typedef uint32_t device_flags_value;
enum device_flags {
DEV_UNKNOWN = 0x00, /* Unknown */
DEV_INPUT = 0x01, /* Record device like mic */
DEV_OUTPUT = 0x02, /* Playback device like speakers */
DEV_SYSTEM_DEFAULT = 0x04, /* System default device */
@@ -109,49 +120,51 @@ enum device_flags {
void
audiounit_stream_stop_internal(cubeb_stream * stm);
static int
audiounit_stream_start_internal(cubeb_stream * stm);
static void
audiounit_close_stream(cubeb_stream * stm);
static int
audiounit_setup_stream(cubeb_stream * stm);
+#if !TARGET_OS_IPHONE
static vector<AudioObjectID>
audiounit_get_devices_of_type(cubeb_device_type devtype);
static UInt32
audiounit_get_device_presentation_latency(AudioObjectID devid,
AudioObjectPropertyScope scope);
-
-#if !TARGET_OS_IPHONE
static AudioObjectID
audiounit_get_default_device_id(cubeb_device_type type);
static int
audiounit_uninstall_device_changed_callback(cubeb_stream * stm);
static int
audiounit_uninstall_system_changed_callback(cubeb_stream * stm);
+#endif
+
static void
audiounit_reinit_stream_async(cubeb_stream * stm, device_flags_value flags);
-#endif
extern cubeb_ops const audiounit_ops;
struct cubeb {
cubeb_ops const * ops = &audiounit_ops;
owned_critical_section mutex;
int active_streams = 0;
uint32_t global_latency_frames = 0;
cubeb_device_collection_changed_callback input_collection_changed_callback =
nullptr;
void * input_collection_changed_user_ptr = nullptr;
cubeb_device_collection_changed_callback output_collection_changed_callback =
nullptr;
void * output_collection_changed_user_ptr = nullptr;
+ #if !TARGET_OS_IPHONE
// Store list of devices to detect changes
vector<AudioObjectID> input_device_array;
vector<AudioObjectID> output_device_array;
+ #endif
// The queue should be released when its no longer needed.
dispatch_queue_t serial_queue =
dispatch_queue_create(DISPATCH_QUEUE_LABEL, DISPATCH_QUEUE_SERIAL);
// Current used channel layout
atomic<cubeb_channel_layout> layout{CUBEB_LAYOUT_UNDEFINED};
uint32_t channels = 0;
};
@@ -181,29 +194,31 @@ to_string(io_side side)
}
}
struct device_info {
AudioDeviceID id = kAudioObjectUnknown;
device_flags_value flags = DEV_UNKNOWN;
};
+#if !TARGET_OS_IPHONE
struct property_listener {
AudioDeviceID device_id;
const AudioObjectPropertyAddress * property_address;
AudioObjectPropertyListenerProc callback;
cubeb_stream * stream;
property_listener(AudioDeviceID id,
const AudioObjectPropertyAddress * address,
AudioObjectPropertyListenerProc proc, cubeb_stream * stm)
: device_id(id), property_address(address), callback(proc), stream(stm)
{
}
};
+#endif
struct cubeb_stream {
explicit cubeb_stream(cubeb * context);
/* Note: Must match cubeb_stream layout in cubeb.c. */
cubeb * context;
void * user_ptr = nullptr;
/**/
@@ -252,32 +267,36 @@ struct cubeb_stream {
/* Latency requested by the user. */
uint32_t latency_frames = 0;
atomic<uint32_t> current_latency_frames{0};
atomic<uint32_t> total_output_latency_frames{0};
unique_ptr<cubeb_resampler, decltype(&cubeb_resampler_destroy)> resampler;
/* This is true if a device change callback is currently running. */
atomic<bool> switching_device{false};
atomic<bool> buffer_size_change_state{false};
+ #if !TARGET_OS_IPHONE
AudioDeviceID aggregate_device_id =
kAudioObjectUnknown; // the aggregate device id
AudioObjectID plugin_id =
kAudioObjectUnknown; // used to create aggregate device
+ #endif
/* Mixer interface */
unique_ptr<cubeb_mixer, decltype(&cubeb_mixer_destroy)> mixer;
/* Buffer where remixing/resampling will occur when upmixing is required */
/* Only accessed from callback thread */
unique_ptr<uint8_t[]> temp_buffer;
size_t temp_buffer_size = 0; // size in bytes.
+ #if !TARGET_OS_IPHONE
/* Listeners indicating what system events are monitored. */
unique_ptr<property_listener> default_input_listener;
unique_ptr<property_listener> default_output_listener;
unique_ptr<property_listener> input_alive_listener;
unique_ptr<property_listener> input_source_listener;
unique_ptr<property_listener> output_source_listener;
+ #endif
};
bool
has_input(cubeb_stream * stm)
{
return stm->input_stream_params.rate != 0;
}
@@ -381,24 +400,16 @@ bool
is_common_sample_rate(Float64 sample_rate)
{
/* Some commonly used sample rates and their multiples and divisors. */
return sample_rate == 8000 || sample_rate == 16000 || sample_rate == 22050 ||
sample_rate == 32000 || sample_rate == 44100 || sample_rate == 48000 ||
sample_rate == 88200 || sample_rate == 96000;
}
-#if TARGET_OS_IPHONE
-typedef UInt32 AudioDeviceID;
-typedef UInt32 AudioObjectID;
-
-#define AudioGetCurrentHostTime mach_absolute_time
-
-#endif
-
uint64_t
ConvertHostTimeToNanos(uint64_t host_time)
{
static struct mach_timebase_info timebase_info;
static bool initialized = false;
if (!initialized) {
mach_timebase_info(&timebase_info);
initialized = true;
@@ -756,23 +767,23 @@ audiounit_init(cubeb ** context, char co
}
static char const *
audiounit_get_backend_id(cubeb * /* ctx */)
{
return "audiounit";
}
-#if !TARGET_OS_IPHONE
static int
audiounit_stream_get_volume(cubeb_stream * stm, float * volume);
static int
audiounit_stream_set_volume(cubeb_stream * stm, float volume);
+#if !TARGET_OS_IPHONE
static int
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;
@@ -806,42 +817,47 @@ audiounit_set_device_info(cubeb_stream *
}
assert(info->id);
assert(info->flags & DEV_INPUT && !(info->flags & DEV_OUTPUT) ||
!(info->flags & DEV_INPUT) && info->flags & DEV_OUTPUT);
return CUBEB_OK;
}
+#endif
static int
audiounit_reinit_stream(cubeb_stream * stm, device_flags_value flags)
{
auto_lock context_lock(stm->context->mutex);
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);
+ int r;
+#if !TARGET_OS_IPHONE
+ r = audiounit_uninstall_device_changed_callback(stm);
if (r != CUBEB_OK) {
LOG("(%p) Could not uninstall all device change listeners.", stm);
}
+#endif
{
auto_lock lock(stm->mutex);
float volume = 0.0;
int vol_rv = CUBEB_ERROR;
if (stm->output_unit) {
vol_rv = audiounit_stream_get_volume(stm, &volume);
}
audiounit_close_stream(stm);
+ #if !TARGET_OS_IPHONE
/* Reinit occurs in one of the following case:
* - When the device is not alive any more
* - When the default system device change.
* - The bluetooth device changed from A2DP to/from HFP/HSP profile
* We first attempt to re-use the same device id, should that fail we will
* default to the (potentially new) default device. */
AudioDeviceID input_device =
flags & DEV_INPUT ? stm->input_device.id : kAudioObjectUnknown;
@@ -861,29 +877,33 @@ audiounit_reinit_stream(cubeb_stream * s
r = audiounit_set_device_info(stm, kAudioObjectUnknown, io_side::OUTPUT);
if (r != CUBEB_OK) {
LOG("(%p) Set output device info failed. This can happen when last media "
"device is unplugged",
stm);
return CUBEB_ERROR;
}
+ #endif
+
if (audiounit_setup_stream(stm) != CUBEB_OK) {
LOG("(%p) Stream reinit failed.", stm);
+ #if !TARGET_OS_IPHONE
if (flags & DEV_INPUT && input_device != kAudioObjectUnknown) {
// Attempt to re-use the same device-id failed, so attempt again with
// default input device.
audiounit_close_stream(stm);
if (audiounit_set_device_info(stm, kAudioObjectUnknown,
io_side::INPUT) != CUBEB_OK ||
audiounit_setup_stream(stm) != CUBEB_OK) {
LOG("(%p) Second stream reinit failed.", stm);
return CUBEB_ERROR;
}
}
+ #endif
}
if (vol_rv == CUBEB_OK) {
audiounit_stream_set_volume(stm, volume);
}
// If the stream was running, start it again.
if (!stm->shutdown) {
@@ -909,27 +929,30 @@ audiounit_reinit_stream_async(cubeb_stre
// Get/SetProperties method from inside notify callback
dispatch_async(stm->context->serial_queue, ^() {
if (stm->destroy_pending) {
ALOG("(%p) stream pending destroy, cancelling reinit task", stm);
return;
}
if (audiounit_reinit_stream(stm, flags) != CUBEB_OK) {
+ #if !TARGET_OS_IPHONE
if (audiounit_uninstall_system_changed_callback(stm) != CUBEB_OK) {
LOG("(%p) Could not uninstall system changed callback", stm);
}
+ #endif
stm->state_callback(stm, stm->user_ptr, CUBEB_STATE_ERROR);
LOG("(%p) Could not reopen the stream after switching.", stm);
}
stm->switching_device = false;
stm->reinit_pending = false;
});
}
+#if !TARGET_OS_IPHONE
static char const *
event_addr_to_string(AudioObjectPropertySelector selector)
{
switch (selector) {
case kAudioHardwarePropertyDefaultOutputDevice:
return "kAudioHardwarePropertyDefaultOutputDevice";
case kAudioHardwarePropertyDefaultInputDevice:
return "kAudioHardwarePropertyDefaultInputDevice";
@@ -1091,16 +1114,17 @@ audiounit_install_device_changed_callbac
rv, stm->input_device.id);
r = CUBEB_ERROR;
}
}
return r;
}
+#if !TARGET_OS_IPHONE
static int
audiounit_install_system_changed_callback(cubeb_stream * stm)
{
OSStatus r;
if (stm->output_unit) {
/* This event will notify us when the default audio device changes,
* for example when the user plugs in a USB headset and the system chooses
@@ -1131,16 +1155,17 @@ audiounit_install_system_changed_callbac
"kAudioHardwarePropertyDefaultInputDevice rv=%d",
r);
return CUBEB_ERROR;
}
}
return CUBEB_OK;
}
+#endif
static int
audiounit_uninstall_device_changed_callback(cubeb_stream * stm)
{
OSStatus rv;
// Failing to uninstall listeners is not a fatal error.
int r = CUBEB_OK;
@@ -1207,17 +1232,17 @@ audiounit_uninstall_system_changed_callb
static int
audiounit_get_acceptable_latency_range(AudioValueRange * latency_range)
{
UInt32 size;
OSStatus r;
AudioDeviceID output_device_id;
AudioObjectPropertyAddress output_device_buffer_size_range = {
kAudioDevicePropertyBufferFrameSizeRange, kAudioDevicePropertyScopeOutput,
- kAudioObjectPropertyElementMaster};
+ kAudioObjectPropertyElementMain};
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;
}
/* Get the buffer size range this device supports */
@@ -1228,17 +1253,16 @@ audiounit_get_acceptable_latency_range(A
&size, latency_range);
if (r != noErr) {
LOG("AudioObjectGetPropertyData/buffer size range rv=%d", r);
return CUBEB_ERROR;
}
return CUBEB_OK;
}
-#endif /* !TARGET_OS_IPHONE */
static AudioObjectID
audiounit_get_default_device_id(cubeb_device_type type)
{
const AudioObjectPropertyAddress * adr;
if (type == CUBEB_DEVICE_TYPE_OUTPUT) {
adr = &DEFAULT_OUTPUT_DEVICE_PROPERTY_ADDRESS;
} else if (type == CUBEB_DEVICE_TYPE_INPUT) {
@@ -1251,31 +1275,32 @@ audiounit_get_default_device_id(cubeb_de
UInt32 size = sizeof(AudioDeviceID);
if (AudioObjectGetPropertyData(kAudioObjectSystemObject, adr, 0, NULL, &size,
&devid) != noErr) {
return kAudioObjectUnknown;
}
return devid;
}
+#endif /* !TARGET_OS_IPHONE */
int
audiounit_get_max_channel_count(cubeb * ctx, uint32_t * max_channels)
{
#if TARGET_OS_IPHONE
// TODO: [[AVAudioSession sharedInstance] maximumOutputNumberOfChannels]
*max_channels = 2;
#else
UInt32 size;
OSStatus r;
AudioDeviceID output_device_id;
AudioStreamBasicDescription stream_format;
AudioObjectPropertyAddress stream_format_address = {
kAudioDevicePropertyStreamFormat, kAudioDevicePropertyScopeOutput,
- kAudioObjectPropertyElementMaster};
+ kAudioObjectPropertyElementMain};
assert(ctx && max_channels);
output_device_id = audiounit_get_default_device_id(CUBEB_DEVICE_TYPE_OUTPUT);
if (output_device_id == kAudioObjectUnknown) {
return CUBEB_ERROR;
}
@@ -1304,52 +1329,52 @@ audiounit_get_min_latency(cubeb * /* ctx
AudioValueRange latency_range;
if (audiounit_get_acceptable_latency_range(&latency_range) != CUBEB_OK) {
LOG("Could not get acceptable latency range.");
return CUBEB_ERROR;
}
*latency_frames =
max<uint32_t>(latency_range.mMinimum, SAFE_MIN_LATENCY_FRAMES);
+ return CUBEB_OK;
#endif
-
- return CUBEB_OK;
}
static int
audiounit_get_preferred_sample_rate(cubeb * /* ctx */, uint32_t * rate)
{
#if TARGET_OS_IPHONE
- // TODO
- return CUBEB_ERROR_NOT_SUPPORTED;
+ *rate = 44100;
+ return CUBEB_OK;
#else
UInt32 size;
OSStatus r;
Float64 fsamplerate;
AudioDeviceID output_device_id;
AudioObjectPropertyAddress samplerate_address = {
kAudioDevicePropertyNominalSampleRate, kAudioObjectPropertyScopeGlobal,
- kAudioObjectPropertyElementMaster};
+ kAudioObjectPropertyElementMain};
output_device_id = audiounit_get_default_device_id(CUBEB_DEVICE_TYPE_OUTPUT);
if (output_device_id == kAudioObjectUnknown) {
return CUBEB_ERROR;
}
size = sizeof(fsamplerate);
r = AudioObjectGetPropertyData(output_device_id, &samplerate_address, 0, NULL,
&size, &fsamplerate);
if (r != noErr) {
return CUBEB_ERROR;
}
*rate = static_cast<uint32_t>(fsamplerate);
+
+ return CUBEB_OK;
#endif
- return CUBEB_OK;
}
static cubeb_channel_layout
audiounit_convert_channel_layout(AudioChannelLayout * layout)
{
// When having one or two channel, force mono or stereo. Some devices (namely,
// Bose QC35, mark 1 and 2), expose a single channel mapped to the right for
// some reason.
@@ -1380,16 +1405,19 @@ audiounit_convert_channel_layout(AudioCh
}
return cl;
}
static cubeb_channel_layout
audiounit_get_preferred_channel_layout(AudioUnit output_unit)
{
+ #if TARGET_OS_IPHONE
+ return CUBEB_LAYOUT_STEREO;
+ #else
OSStatus rv = noErr;
UInt32 size = 0;
rv = AudioUnitGetPropertyInfo(
output_unit, kAudioDevicePropertyPreferredChannelLayout,
kAudioUnitScope_Output, AU_OUT_BUS, &size, nullptr);
if (rv != noErr) {
LOG("AudioUnitGetPropertyInfo/kAudioDevicePropertyPreferredChannelLayout "
"rv=%d",
@@ -1404,16 +1432,17 @@ audiounit_get_preferred_channel_layout(A
kAudioUnitScope_Output, AU_OUT_BUS, layout.get(), &size);
if (rv != noErr) {
LOG("AudioUnitGetProperty/kAudioDevicePropertyPreferredChannelLayout rv=%d",
rv);
return CUBEB_LAYOUT_UNDEFINED;
}
return audiounit_convert_channel_layout(layout.get());
+ #endif
}
static cubeb_channel_layout
audiounit_get_current_channel_layout(AudioUnit output_unit)
{
OSStatus rv = noErr;
UInt32 size = 0;
rv = AudioUnitGetPropertyInfo(
@@ -1437,18 +1466,20 @@ audiounit_get_current_channel_layout(Aud
}
return audiounit_convert_channel_layout(layout.get());
}
static int
audiounit_create_unit(AudioUnit * unit, device_info * device);
+#if !TARGET_OS_IPHONE
static OSStatus
audiounit_remove_device_listener(cubeb * context, cubeb_device_type devtype);
+#endif
static void
audiounit_destroy(cubeb * ctx)
{
{
auto_lock lock(ctx->mutex);
// Disabling this assert for bug 1083664 -- we seem to leak a stream
@@ -1460,23 +1491,25 @@ audiounit_destroy(cubeb * ctx)
// Destroying a cubeb context with device collection callbacks registered
// is misuse of the API, assert then attempt to clean up.
assert(!ctx->input_collection_changed_callback &&
!ctx->input_collection_changed_user_ptr &&
!ctx->output_collection_changed_callback &&
!ctx->output_collection_changed_user_ptr);
+ #if !TARGET_OS_IPHONE
/* Unregister the callback if necessary. */
if (ctx->input_collection_changed_callback) {
audiounit_remove_device_listener(ctx, CUBEB_DEVICE_TYPE_INPUT);
}
if (ctx->output_collection_changed_callback) {
audiounit_remove_device_listener(ctx, CUBEB_DEVICE_TYPE_OUTPUT);
}
+ #endif
}
dispatch_release(ctx->serial_queue);
delete ctx;
}
static void
@@ -1594,23 +1627,24 @@ audiounit_layout_init(cubeb_stream * stm
}
stm->context->layout = audiounit_get_current_channel_layout(stm->output_unit);
audiounit_set_channel_layout(stm->output_unit, io_side::OUTPUT,
stm->context->layout);
}
+#if !TARGET_OS_IPHONE
static vector<AudioObjectID>
audiounit_get_sub_devices(AudioDeviceID device_id)
{
vector<AudioDeviceID> sub_devices;
AudioObjectPropertyAddress property_address = {
kAudioAggregateDevicePropertyActiveSubDeviceList,
- kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster};
+ kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMain};
UInt32 size = 0;
OSStatus rv = AudioObjectGetPropertyDataSize(device_id, &property_address, 0,
nullptr, &size);
if (rv != noErr) {
sub_devices.push_back(device_id);
return sub_devices;
}
@@ -1629,17 +1663,17 @@ audiounit_get_sub_devices(AudioDeviceID
}
static int
audiounit_create_blank_aggregate_device(AudioObjectID * plugin_id,
AudioDeviceID * aggregate_device_id)
{
AudioObjectPropertyAddress address_plugin_bundle_id = {
kAudioHardwarePropertyPlugInForBundleID, kAudioObjectPropertyScopeGlobal,
- kAudioObjectPropertyElementMaster};
+ kAudioObjectPropertyElementMain};
UInt32 size = 0;
OSStatus r = AudioObjectGetPropertyDataSize(
kAudioObjectSystemObject, &address_plugin_bundle_id, 0, NULL, &size);
if (r != noErr) {
LOG("AudioObjectGetPropertyDataSize/"
"kAudioHardwarePropertyPlugInForBundleID, rv=%d",
r);
return CUBEB_ERROR;
@@ -1659,17 +1693,17 @@ audiounit_create_blank_aggregate_device(
LOG("AudioObjectGetPropertyData/kAudioHardwarePropertyPlugInForBundleID, "
"rv=%d",
r);
return CUBEB_ERROR;
}
AudioObjectPropertyAddress create_aggregate_device_address = {
kAudioPlugInCreateAggregateDevice, kAudioObjectPropertyScopeGlobal,
- kAudioObjectPropertyElementMaster};
+ kAudioObjectPropertyElementMain};
r = AudioObjectGetPropertyDataSize(
*plugin_id, &create_aggregate_device_address, 0, nullptr, &size);
if (r != noErr) {
LOG("AudioObjectGetPropertyDataSize/kAudioPlugInCreateAggregateDevice, "
"rv=%d",
r);
return CUBEB_ERROR;
}
@@ -1731,17 +1765,17 @@ audiounit_create_blank_aggregate_device(
// object is increased.
static CFStringRef
get_device_name(AudioDeviceID id)
{
UInt32 size = sizeof(CFStringRef);
CFStringRef UIname = nullptr;
AudioObjectPropertyAddress address_uuid = {kAudioDevicePropertyDeviceUID,
kAudioObjectPropertyScopeGlobal,
- kAudioObjectPropertyElementMaster};
+ kAudioObjectPropertyElementMain};
OSStatus err =
AudioObjectGetPropertyData(id, &address_uuid, 0, nullptr, &size, &UIname);
return (err == noErr) ? UIname : NULL;
}
static int
audiounit_set_aggregate_sub_device_list(AudioDeviceID aggregate_device_id,
AudioDeviceID input_device_id,
@@ -1774,17 +1808,17 @@ audiounit_set_aggregate_sub_device_list(
return CUBEB_ERROR;
}
CFArrayAppendValue(aggregate_sub_devices_array, ref);
CFRelease(ref);
}
AudioObjectPropertyAddress aggregate_sub_device_list = {
kAudioAggregateDevicePropertyFullSubDeviceList,
- kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster};
+ kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMain};
UInt32 size = sizeof(CFMutableArrayRef);
OSStatus rv = AudioObjectSetPropertyData(
aggregate_device_id, &aggregate_sub_device_list, 0, nullptr, size,
&aggregate_sub_devices_array);
CFRelease(aggregate_sub_devices_array);
if (rv != noErr) {
LOG("AudioObjectSetPropertyData/"
"kAudioAggregateDevicePropertyFullSubDeviceList, rv=%d",
@@ -1796,17 +1830,17 @@ audiounit_set_aggregate_sub_device_list(
}
static int
audiounit_set_master_aggregate_device(const AudioDeviceID aggregate_device_id)
{
assert(aggregate_device_id != kAudioObjectUnknown);
AudioObjectPropertyAddress master_aggregate_sub_device = {
kAudioAggregateDevicePropertyMasterSubDevice,
- kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster};
+ kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMain};
// Master become the 1st output sub device
AudioDeviceID output_device_id =
audiounit_get_default_device_id(CUBEB_DEVICE_TYPE_OUTPUT);
const vector<AudioDeviceID> output_sub_devices =
audiounit_get_sub_devices(output_device_id);
CFStringRef master_sub_device = get_device_name(output_sub_devices[0]);
@@ -1829,17 +1863,17 @@ audiounit_set_master_aggregate_device(co
static int
audiounit_activate_clock_drift_compensation(
const AudioDeviceID aggregate_device_id)
{
assert(aggregate_device_id != kAudioObjectUnknown);
AudioObjectPropertyAddress address_owned = {
kAudioObjectPropertyOwnedObjects, kAudioObjectPropertyScopeGlobal,
- kAudioObjectPropertyElementMaster};
+ kAudioObjectPropertyElementMain};
UInt32 qualifier_data_size = sizeof(AudioObjectID);
AudioClassID class_id = kAudioSubDeviceClassID;
void * qualifier_data = &class_id;
UInt32 size = 0;
OSStatus rv = AudioObjectGetPropertyDataSize(
aggregate_device_id, &address_owned, qualifier_data_size, qualifier_data,
&size);
@@ -1861,17 +1895,17 @@ audiounit_activate_clock_drift_compensat
if (rv != noErr) {
LOG("AudioObjectGetPropertyData/kAudioObjectPropertyOwnedObjects, rv=%d",
rv);
return CUBEB_ERROR;
}
AudioObjectPropertyAddress address_drift = {
kAudioSubDevicePropertyDriftCompensation, kAudioObjectPropertyScopeGlobal,
- kAudioObjectPropertyElementMaster};
+ kAudioObjectPropertyElementMain};
// Start from the second device since the first is the master clock
for (UInt32 i = 1; i < subdevices_num; ++i) {
UInt32 drift_compensation_value = 1;
rv = AudioObjectSetPropertyData(sub_devices[i], &address_drift, 0, nullptr,
sizeof(UInt32), &drift_compensation_value);
if (rv != noErr) {
LOG("AudioObjectSetPropertyData/"
@@ -1930,17 +1964,17 @@ audiounit_workaround_for_airpod(cubeb_st
&output_min_rate, &output_max_rate, &output_nominal_rate);
LOG("(%p) Output device %u, name: %s, min: %u, max: %u, nominal rate: %u",
stm, stm->output_device.id, output_device_info.friendly_name,
output_min_rate, output_max_rate, output_nominal_rate);
Float64 rate = input_nominal_rate;
AudioObjectPropertyAddress addr = {kAudioDevicePropertyNominalSampleRate,
kAudioObjectPropertyScopeGlobal,
- kAudioObjectPropertyElementMaster};
+ kAudioObjectPropertyElementMain};
OSStatus rv = AudioObjectSetPropertyData(stm->aggregate_device_id, &addr, 0,
nullptr, sizeof(Float64), &rate);
if (rv != noErr) {
LOG("Non fatal error, "
"AudioObjectSetPropertyData/kAudioDevicePropertyNominalSampleRate, "
"rv=%d",
rv);
@@ -2014,17 +2048,17 @@ audiounit_create_aggregate_device(cubeb_
static int
audiounit_destroy_aggregate_device(AudioObjectID plugin_id,
AudioDeviceID * aggregate_device_id)
{
assert(aggregate_device_id && *aggregate_device_id != kAudioDeviceUnknown &&
plugin_id != kAudioObjectUnknown);
AudioObjectPropertyAddress destroy_aggregate_device_addr = {
kAudioPlugInDestroyAggregateDevice, kAudioObjectPropertyScopeGlobal,
- kAudioObjectPropertyElementMaster};
+ kAudioObjectPropertyElementMain};
UInt32 size;
OSStatus rv = AudioObjectGetPropertyDataSize(
plugin_id, &destroy_aggregate_device_addr, 0, NULL, &size);
if (rv != noErr) {
LOG("AudioObjectGetPropertyDataSize/kAudioPlugInDestroyAggregateDevice, "
"rv=%d",
rv);
return CUBEB_ERROR;
@@ -2037,16 +2071,17 @@ audiounit_destroy_aggregate_device(Audio
rv);
return CUBEB_ERROR;
}
LOG("Destroyed aggregate device %d", *aggregate_device_id);
*aggregate_device_id = kAudioObjectUnknown;
return CUBEB_OK;
}
+#endif
static int
audiounit_new_unit_instance(AudioUnit * unit, device_info * device)
{
AudioComponentDescription desc;
AudioComponent comp;
OSStatus rv;
@@ -2173,16 +2208,19 @@ audiounit_init_input_linear_buffer(cubeb
assert(stream->input_linear_buffer->length() == 0);
return CUBEB_OK;
}
static uint32_t
audiounit_clamp_latency(cubeb_stream * stm, uint32_t latency_frames)
{
+ #if TARGET_OS_IPHONE
+ return latency_frames;
+ #else
// For the 1st stream set anything within safe min-max
assert(audiounit_active_streams(stm->context) > 0);
if (audiounit_active_streams(stm->context) == 1) {
return max(min<uint32_t>(latency_frames, SAFE_MAX_LATENCY_FRAMES),
SAFE_MIN_LATENCY_FRAMES);
}
assert(stm->output_unit);
@@ -2233,18 +2271,20 @@ audiounit_clamp_latency(cubeb_stream * s
} else if (output_buffer_size != 0) {
upper_latency_limit = output_buffer_size;
} else {
upper_latency_limit = SAFE_MAX_LATENCY_FRAMES;
}
return max(min<uint32_t>(latency_frames, upper_latency_limit),
SAFE_MIN_LATENCY_FRAMES);
+ #endif
}
+#if !TARGET_OS_IPHONE
/*
* Change buffer size is prone to deadlock thus we change it
* following the steps:
* - register a listener for the buffer size property
* - change the property
* - wait until the listener is executed
* - property has changed, remove the listener
* */
@@ -2285,21 +2325,25 @@ buffer_size_changed_callback(void * inCl
"= %d for scope %d",
stm, au_type, new_buffer_size, inScope);
}
stm->buffer_size_change_state = true;
break;
}
}
}
+#endif
static int
audiounit_set_buffer_size(cubeb_stream * stm, uint32_t new_size_frames,
io_side side)
{
+ #if TARGET_OS_IPHONE
+ return CUBEB_OK;
+ #else
AudioUnit au = stm->output_unit;
AudioUnitScope au_scope = kAudioUnitScope_Input;
AudioUnitElement au_element = AU_OUT_BUS;
if (side == io_side::INPUT) {
au = stm->input_unit;
au_scope = kAudioUnitScope_Output;
au_element = AU_IN_BUS;
@@ -2377,16 +2421,17 @@ audiounit_set_buffer_size(cubeb_stream *
if (!stm->buffer_size_change_state && count >= 30) {
LOG("(%p) Error, did not get buffer size change callback ...", stm);
return CUBEB_ERROR;
}
LOG("(%p) %s buffer size changed to %u frames.", stm, to_string(side),
new_size_frames);
return CUBEB_OK;
+ #endif
}
static int
audiounit_configure_input(cubeb_stream * stm)
{
assert(stm && stm->input_unit);
int r = 0;
@@ -2593,16 +2638,17 @@ audiounit_setup_stream(cubeb_stream * st
return CUBEB_ERROR_NOT_SUPPORTED;
}
int r = 0;
device_info in_dev_info = stm->input_device;
device_info out_dev_info = stm->output_device;
+ #if !TARGET_OS_IPHONE
if (has_input(stm) && has_output(stm) &&
stm->input_device.id != stm->output_device.id) {
r = audiounit_create_aggregate_device(stm);
if (r != CUBEB_OK) {
stm->aggregate_device_id = kAudioObjectUnknown;
LOG("(%p) Create aggregate devices failed.", stm);
// !!!NOTE: It is not necessary to return here. If it does not
// return it will fallback to the old implementation. The intention
@@ -2610,16 +2656,20 @@ audiounit_setup_stream(cubeb_stream * st
// it after a couple of weeks.
return r;
} else {
in_dev_info.id = out_dev_info.id = stm->aggregate_device_id;
in_dev_info.flags = DEV_INPUT;
out_dev_info.flags = DEV_OUTPUT;
}
}
+ #else
+ in_dev_info.flags = DEV_SYSTEM_DEFAULT | DEV_INPUT;
+ out_dev_info.flags = DEV_SYSTEM_DEFAULT | DEV_OUTPUT;
+ #endif
if (has_input(stm)) {
r = audiounit_create_unit(&stm->input_unit, &in_dev_info);
if (r != CUBEB_OK) {
LOG("(%p) AudioUnit creation for input failed.", stm);
return r;
}
}
@@ -2751,18 +2801,20 @@ audiounit_setup_stream(cubeb_stream * st
if (stm->output_unit != NULL) {
r = AudioUnitInitialize(stm->output_unit);
if (r != noErr) {
LOG("AudioUnitInitialize/output rv=%d", r);
return CUBEB_ERROR;
}
+ #if !TARGET_OS_IPHONE
stm->current_latency_frames = audiounit_get_device_presentation_latency(
stm->output_device.id, kAudioDevicePropertyScopeOutput);
+ #endif
Float64 unit_s;
UInt32 size = sizeof(unit_s);
if (AudioUnitGetProperty(stm->output_unit, kAudioUnitProperty_Latency,
kAudioUnitScope_Global, 0, &unit_s,
&size) == noErr) {
stm->current_latency_frames +=
static_cast<uint32_t>(unit_s * stm->output_desc.mSampleRate);
@@ -2772,20 +2824,22 @@ audiounit_setup_stream(cubeb_stream * st
if (stm->input_unit && stm->output_unit) {
// According to the I/O hardware rate it is expected a specific pattern of
// callbacks for example is input is 44100 and output is 48000 we expected
// no more than 2 out callback in a row.
stm->expected_output_callbacks_in_a_row =
ceilf(stm->output_hw_rate / stm->input_hw_rate);
}
+ #if !TARGET_OS_IPHONE
r = audiounit_install_device_changed_callback(stm);
if (r != CUBEB_OK) {
LOG("(%p) Could not install all device change callback.", stm);
}
+ #endif
return CUBEB_OK;
}
cubeb_stream::cubeb_stream(cubeb * context)
: context(context), resampler(nullptr, cubeb_resampler_destroy),
mixer(nullptr, cubeb_mixer_destroy)
{
@@ -2823,51 +2877,57 @@ audiounit_stream_init(cubeb * context, c
stm->latency_frames = latency_frames;
if ((input_device && !input_stream_params) ||
(output_device && !output_stream_params)) {
return CUBEB_ERROR_INVALID_PARAMETER;
}
if (input_stream_params) {
stm->input_stream_params = *input_stream_params;
+ #if !TARGET_OS_IPHONE
r = audiounit_set_device_info(
stm.get(), reinterpret_cast<uintptr_t>(input_device), io_side::INPUT);
if (r != CUBEB_OK) {
LOG("(%p) Fail to set device info for input.", stm.get());
return r;
}
+ #endif
}
if (output_stream_params) {
stm->output_stream_params = *output_stream_params;
+ #if !TARGET_OS_IPHONE
r = audiounit_set_device_info(
stm.get(), reinterpret_cast<uintptr_t>(output_device), io_side::OUTPUT);
if (r != CUBEB_OK) {
LOG("(%p) Fail to set device info for output.", stm.get());
return r;
}
+ #endif
}
{
// It's not critical to lock here, because no other thread has been started
// yet, but it allows to assert that the lock has been taken in
// `audiounit_setup_stream`.
auto_lock lock(stm->mutex);
r = audiounit_setup_stream(stm.get());
}
if (r != CUBEB_OK) {
LOG("(%p) Could not setup the audiounit stream.", stm.get());
return r;
}
+ #if !TARGET_OS_IPHONE
r = audiounit_install_system_changed_callback(stm.get());
if (r != CUBEB_OK) {
LOG("(%p) Could not install the device change callback.", stm.get());
return r;
}
+ #endif
*stream = stm.release();
LOG("(%p) Cubeb stream init successful.", *stream);
return CUBEB_OK;
}
static void
audiounit_close_stream(cubeb_stream * stm)
@@ -2886,54 +2946,60 @@ audiounit_close_stream(cubeb_stream * st
AudioUnitUninitialize(stm->output_unit);
AudioComponentInstanceDispose(stm->output_unit);
stm->output_unit = nullptr;
}
stm->resampler.reset();
stm->mixer.reset();
+ #if !TARGET_OS_IPHONE
if (stm->aggregate_device_id != kAudioObjectUnknown) {
audiounit_destroy_aggregate_device(stm->plugin_id,
&stm->aggregate_device_id);
stm->aggregate_device_id = kAudioObjectUnknown;
}
+ #endif
}
static void
audiounit_stream_destroy_internal(cubeb_stream * stm)
{
stm->context->mutex.assert_current_thread_owns();
+#if !TARGET_OS_IPHONE
int r = audiounit_uninstall_system_changed_callback(stm);
if (r != CUBEB_OK) {
LOG("(%p) Could not uninstall the device changed callback", stm);
}
r = audiounit_uninstall_device_changed_callback(stm);
if (r != CUBEB_OK) {
LOG("(%p) Could not uninstall all device change listeners", stm);
}
+#endif
auto_lock lock(stm->mutex);
audiounit_close_stream(stm);
assert(audiounit_active_streams(stm->context) >= 1);
audiounit_decrement_active_streams(stm->context);
}
static void
audiounit_stream_destroy(cubeb_stream * stm)
{
+ #if !TARGET_OS_IPHONE
int r = audiounit_uninstall_system_changed_callback(stm);
if (r != CUBEB_OK) {
LOG("(%p) Could not uninstall the device changed callback", stm);
}
r = audiounit_uninstall_device_changed_callback(stm);
if (r != CUBEB_OK) {
LOG("(%p) Could not uninstall all device change listeners", stm);
}
+ #endif
if (!stm->shutdown.load()) {
auto_lock context_lock(stm->context->mutex);
audiounit_stream_stop_internal(stm);
stm->shutdown = true;
}
stm->destroy_pending = true;
@@ -3081,16 +3147,17 @@ convert_uint32_into_string(UInt32 data)
// Reverse 0xWXYZ into 0xZYXW.
str[0] = (char)(data >> 24);
str[1] = (char)(data >> 16);
str[2] = (char)(data >> 8);
str[3] = (char)(data);
return str;
}
+#if !TARGET_OS_IPHONE
int
audiounit_get_default_device_datasource(cubeb_device_type type, UInt32 * data)
{
AudioDeviceID id = audiounit_get_default_device_id(type);
if (id == kAudioObjectUnknown) {
return CUBEB_ERROR;
}
@@ -3102,38 +3169,43 @@ audiounit_get_default_device_datasource(
: &OUTPUT_DATA_SOURCE_PROPERTY_ADDRESS,
0, NULL, &size, data);
if (r != noErr) {
*data = 0;
}
return CUBEB_OK;
}
+#endif
int
audiounit_get_default_device_name(cubeb_stream * stm,
cubeb_device * const device,
cubeb_device_type type)
{
+#if TARGET_OS_IPHONE
+ return CUBEB_ERROR_NOT_SUPPORTED;
+#else
assert(stm);
assert(device);
UInt32 data;
int r = audiounit_get_default_device_datasource(type, &data);
if (r != CUBEB_OK) {
return r;
}
char ** name = type == CUBEB_DEVICE_TYPE_INPUT ? &device->input_name
: &device->output_name;
*name = convert_uint32_into_string(data).release();
if (!strlen(*name)) { // empty string.
LOG("(%p) name of %s device is empty!", stm,
type == CUBEB_DEVICE_TYPE_INPUT ? "input" : "output");
}
return CUBEB_OK;
+ #endif
}
int
audiounit_stream_get_current_device(cubeb_stream * stm,
cubeb_device ** const device)
{
#if TARGET_OS_IPHONE
// TODO
@@ -3178,16 +3250,17 @@ audiounit_stream_register_device_changed
auto_lock dev_cb_lock(stream->device_changed_callback_lock);
/* Note: second register without unregister first causes 'nope' error.
* Current implementation requires unregister before register a new cb. */
assert(!device_changed_callback || !stream->device_changed_callback);
stream->device_changed_callback = device_changed_callback;
return CUBEB_OK;
}
+#if !TARGET_OS_IPHONE
static char *
audiounit_strref_to_cstr_utf8(CFStringRef strref)
{
CFIndex len, size;
char * ret;
if (strref == NULL) {
return NULL;
}
@@ -3199,22 +3272,24 @@ audiounit_strref_to_cstr_utf8(CFStringRe
if (!CFStringGetCString(strref, ret, size, kCFStringEncodingUTF8)) {
delete[] ret;
ret = NULL;
}
return ret;
}
-
+#endif
+
+#if !TARGET_OS_IPHONE
static uint32_t
audiounit_get_channel_count(AudioObjectID devid, AudioObjectPropertyScope scope)
{
AudioObjectPropertyAddress adr = {0, scope,
- kAudioObjectPropertyElementMaster};
+ kAudioObjectPropertyElementMain};
UInt32 size = 0;
uint32_t i, ret = 0;
adr.mSelector = kAudioDevicePropertyStreamConfiguration;
if (AudioObjectGetPropertyDataSize(devid, &adr, 0, NULL, &size) == noErr &&
size > 0) {
AudioBufferList * list = static_cast<AudioBufferList *>(alloca(size));
@@ -3230,17 +3305,17 @@ audiounit_get_channel_count(AudioObjectI
static void
audiounit_get_available_samplerate(AudioObjectID devid,
AudioObjectPropertyScope scope,
uint32_t * min, uint32_t * max,
uint32_t * def)
{
AudioObjectPropertyAddress adr = {0, scope,
- kAudioObjectPropertyElementMaster};
+ kAudioObjectPropertyElementMain};
adr.mSelector = kAudioDevicePropertyNominalSampleRate;
if (AudioObjectHasProperty(devid, &adr)) {
UInt32 size = sizeof(Float64);
Float64 fvalue = 0.0;
if (AudioObjectGetPropertyData(devid, &adr, 0, NULL, &size, &fvalue) ==
noErr) {
*def = fvalue;
@@ -3272,17 +3347,17 @@ audiounit_get_available_samplerate(Audio
}
}
static UInt32
audiounit_get_device_presentation_latency(AudioObjectID devid,
AudioObjectPropertyScope scope)
{
AudioObjectPropertyAddress adr = {0, scope,
- kAudioObjectPropertyElementMaster};
+ kAudioObjectPropertyElementMain};
UInt32 size, dev, stream = 0;
AudioStreamID sid[1];
adr.mSelector = kAudioDevicePropertyLatency;
size = sizeof(UInt32);
if (AudioObjectGetPropertyData(devid, &adr, 0, NULL, &size, &dev) != noErr) {
dev = 0;
}
@@ -3297,28 +3372,32 @@ audiounit_get_device_presentation_latenc
return dev + stream;
}
static int
audiounit_create_device_from_hwdev(cubeb_device_info * dev_info,
AudioObjectID devid, cubeb_device_type type)
{
- AudioObjectPropertyAddress adr = {0, 0, kAudioObjectPropertyElementMaster};
+ AudioObjectPropertyAddress adr = {0, 0, kAudioObjectPropertyElementMain};
UInt32 size;
if (type == CUBEB_DEVICE_TYPE_OUTPUT) {
adr.mScope = kAudioDevicePropertyScopeOutput;
} else if (type == CUBEB_DEVICE_TYPE_INPUT) {
adr.mScope = kAudioDevicePropertyScopeInput;
} else {
return CUBEB_ERROR;
}
+ #if TARGET_OS_IPHONE
+ UINT32 ch = 2;
+ #else
UInt32 ch = audiounit_get_channel_count(devid, adr.mScope);
+ #endif
if (ch == 0) {
return CUBEB_ERROR;
}
PodZero(dev_info, 1);
CFStringRef device_id_str = nullptr;
size = sizeof(CFStringRef);
@@ -3412,17 +3491,26 @@ audiounit_create_device_from_hwdev(cubeb
bool
is_aggregate_device(cubeb_device_info * device_info)
{
assert(device_info->friendly_name);
return !strncmp(device_info->friendly_name, PRIVATE_AGGREGATE_DEVICE_NAME,
strlen(PRIVATE_AGGREGATE_DEVICE_NAME));
}
-
+#endif
+
+#if TARGET_OS_IPHONE
+static int
+audiounit_enumerate_devices(cubeb * /* context */, cubeb_device_type type,
+ cubeb_device_collection * collection)
+{
+ return CUBEB_ERROR_NOT_SUPPORTED;
+}
+#else
static int
audiounit_enumerate_devices(cubeb * /* context */, cubeb_device_type type,
cubeb_device_collection * collection)
{
vector<AudioObjectID> input_devs;
vector<AudioObjectID> output_devs;
// Count number of input and output devices. This is not
@@ -3478,29 +3566,35 @@ audiounit_enumerate_devices(cubeb * /* c
static void
audiounit_device_destroy(cubeb_device_info * device)
{
delete[] device->device_id;
delete[] device->friendly_name;
delete[] device->vendor_name;
}
+#endif
static int
audiounit_device_collection_destroy(cubeb * /* context */,
cubeb_device_collection * collection)
{
+ #if TARGET_OS_IPHONE
+ return CUBEB_ERROR_NOT_SUPPORTED;
+ #else
for (size_t i = 0; i < collection->count; i++) {
audiounit_device_destroy(&collection->device[i]);
}
delete[] collection->device;
return CUBEB_OK;
+ #endif
}
+#if !TARGET_OS_IPHONE
static vector<AudioObjectID>
audiounit_get_devices_of_type(cubeb_device_type devtype)
{
UInt32 size = 0;
OSStatus ret = AudioObjectGetPropertyDataSize(
kAudioObjectSystemObject, &DEVICES_PROPERTY_ADDRESS, 0, NULL, &size);
if (ret != noErr) {
return vector<AudioObjectID>();
@@ -3653,17 +3747,28 @@ audiounit_remove_device_listener(cubeb *
context->output_collection_changed_callback) {
return noErr;
}
/* Note: unregister a non registered cb is not a problem, not checking. */
return AudioObjectRemovePropertyListener(
kAudioObjectSystemObject, &DEVICES_PROPERTY_ADDRESS,
audiounit_collection_changed_callback, context);
}
-
+#endif
+
+#if TARGET_OS_IPHONE
+int
+audiounit_register_device_collection_changed(
+ cubeb * context, cubeb_device_type devtype,
+ cubeb_device_collection_changed_callback collection_changed_callback,
+ void * user_ptr)
+{
+ return CUBEB_ERROR_NOT_SUPPORTED;
+}
+#else
int
audiounit_register_device_collection_changed(
cubeb * context, cubeb_device_type devtype,
cubeb_device_collection_changed_callback collection_changed_callback,
void * user_ptr)
{
if (devtype == CUBEB_DEVICE_TYPE_UNKNOWN) {
return CUBEB_ERROR_INVALID_PARAMETER;
@@ -3673,16 +3778,17 @@ audiounit_register_device_collection_cha
if (collection_changed_callback) {
ret = audiounit_add_device_listener(context, devtype,
collection_changed_callback, user_ptr);
} else {
ret = audiounit_remove_device_listener(context, devtype);
}
return (ret == noErr) ? CUBEB_OK : CUBEB_ERROR;
}
+#endif
cubeb_ops const audiounit_ops = {
/*.init =*/audiounit_init,
/*.get_backend_id =*/audiounit_get_backend_id,
/*.get_max_channel_count =*/audiounit_get_max_channel_count,
/*.get_min_latency =*/audiounit_get_min_latency,
/*.get_preferred_sample_rate =*/audiounit_get_preferred_sample_rate,
/*.get_supported_input_processing_params =*/NULL,