tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

0003-audiounit-ios-compile-fixes.patch (46513B)


      1 diff --git a/src/cubeb_audiounit.cpp b/src/cubeb_audiounit.cpp
      2 --- a/src/cubeb_audiounit.cpp
      3 +++ b/src/cubeb_audiounit.cpp
      4 @@ -36,16 +36,25 @@
      5 #include <vector>
      6 
      7 using namespace std;
      8 
      9 #if MAC_OS_X_VERSION_MIN_REQUIRED < 101000
     10 typedef UInt32 AudioFormatFlags;
     11 #endif
     12 
     13 +#if TARGET_OS_IPHONE
     14 +typedef UInt32 AudioDeviceID;
     15 +typedef UInt32 AudioObjectID;
     16 +const UInt32 kAudioObjectUnknown = 0;
     17 +
     18 +#define AudioGetCurrentHostTime mach_absolute_time
     19 +
     20 +#endif
     21 +
     22 #define AU_OUT_BUS 0
     23 #define AU_IN_BUS 1
     24 
     25 const char * DISPATCH_QUEUE_LABEL = "org.mozilla.cubeb";
     26 const char * PRIVATE_AGGREGATE_DEVICE_NAME = "CubebAggregateDevice";
     27 
     28 #ifdef ALOGV
     29 #undef ALOGV
     30 @@ -60,45 +69,47 @@ const char * PRIVATE_AGGREGATE_DEVICE_NA
     31 #undef ALOG
     32 #endif
     33 #define ALOG(msg, ...)                                                         \
     34   dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0),   \
     35                  ^{                                                            \
     36                    LOG(msg, ##__VA_ARGS__);                                    \
     37                  })
     38 
     39 +#if !TARGET_OS_IPHONE
     40 /* Testing empirically, some headsets report a minimal latency that is very
     41  * low, but this does not work in practice. Lie and say the minimum is 256
     42  * frames. */
     43 const uint32_t SAFE_MIN_LATENCY_FRAMES = 128;
     44 const uint32_t SAFE_MAX_LATENCY_FRAMES = 512;
     45 
     46 const AudioObjectPropertyAddress DEFAULT_INPUT_DEVICE_PROPERTY_ADDRESS = {
     47     kAudioHardwarePropertyDefaultInputDevice, kAudioObjectPropertyScopeGlobal,
     48 -    kAudioObjectPropertyElementMaster};
     49 +    kAudioObjectPropertyElementMain};
     50 
     51 const AudioObjectPropertyAddress DEFAULT_OUTPUT_DEVICE_PROPERTY_ADDRESS = {
     52     kAudioHardwarePropertyDefaultOutputDevice, kAudioObjectPropertyScopeGlobal,
     53 -    kAudioObjectPropertyElementMaster};
     54 +    kAudioObjectPropertyElementMain};
     55 
     56 const AudioObjectPropertyAddress DEVICE_IS_ALIVE_PROPERTY_ADDRESS = {
     57     kAudioDevicePropertyDeviceIsAlive, kAudioObjectPropertyScopeGlobal,
     58 -    kAudioObjectPropertyElementMaster};
     59 +    kAudioObjectPropertyElementMain};
     60 
     61 const AudioObjectPropertyAddress DEVICES_PROPERTY_ADDRESS = {
     62     kAudioHardwarePropertyDevices, kAudioObjectPropertyScopeGlobal,
     63 -    kAudioObjectPropertyElementMaster};
     64 +    kAudioObjectPropertyElementMain};
     65 
     66 const AudioObjectPropertyAddress INPUT_DATA_SOURCE_PROPERTY_ADDRESS = {
     67     kAudioDevicePropertyDataSource, kAudioDevicePropertyScopeInput,
     68 -    kAudioObjectPropertyElementMaster};
     69 +    kAudioObjectPropertyElementMain};
     70 
     71 const AudioObjectPropertyAddress OUTPUT_DATA_SOURCE_PROPERTY_ADDRESS = {
     72     kAudioDevicePropertyDataSource, kAudioDevicePropertyScopeOutput,
     73 -    kAudioObjectPropertyElementMaster};
     74 +    kAudioObjectPropertyElementMain};
     75 +#endif
     76 
     77 typedef uint32_t device_flags_value;
     78 
     79 enum device_flags {
     80   DEV_UNKNOWN = 0x00,        /* Unknown */
     81   DEV_INPUT = 0x01,          /* Record device like mic */
     82   DEV_OUTPUT = 0x02,         /* Playback device like speakers */
     83   DEV_SYSTEM_DEFAULT = 0x04, /* System default device */
     84 @@ -109,49 +120,51 @@ enum device_flags {
     85 void
     86 audiounit_stream_stop_internal(cubeb_stream * stm);
     87 static int
     88 audiounit_stream_start_internal(cubeb_stream * stm);
     89 static void
     90 audiounit_close_stream(cubeb_stream * stm);
     91 static int
     92 audiounit_setup_stream(cubeb_stream * stm);
     93 +#if !TARGET_OS_IPHONE
     94 static vector<AudioObjectID>
     95 audiounit_get_devices_of_type(cubeb_device_type devtype);
     96 static UInt32
     97 audiounit_get_device_presentation_latency(AudioObjectID devid,
     98                                           AudioObjectPropertyScope scope);
     99 -
    100 -#if !TARGET_OS_IPHONE
    101 static AudioObjectID
    102 audiounit_get_default_device_id(cubeb_device_type type);
    103 static int
    104 audiounit_uninstall_device_changed_callback(cubeb_stream * stm);
    105 static int
    106 audiounit_uninstall_system_changed_callback(cubeb_stream * stm);
    107 +#endif
    108 +
    109 static void
    110 audiounit_reinit_stream_async(cubeb_stream * stm, device_flags_value flags);
    111 -#endif
    112 
    113 extern cubeb_ops const audiounit_ops;
    114 
    115 struct cubeb {
    116   cubeb_ops const * ops = &audiounit_ops;
    117   owned_critical_section mutex;
    118   int active_streams = 0;
    119   uint32_t global_latency_frames = 0;
    120   cubeb_device_collection_changed_callback input_collection_changed_callback =
    121       nullptr;
    122   void * input_collection_changed_user_ptr = nullptr;
    123   cubeb_device_collection_changed_callback output_collection_changed_callback =
    124       nullptr;
    125   void * output_collection_changed_user_ptr = nullptr;
    126 +  #if !TARGET_OS_IPHONE
    127   // Store list of devices to detect changes
    128   vector<AudioObjectID> input_device_array;
    129   vector<AudioObjectID> output_device_array;
    130 +  #endif
    131   // The queue should be released when it’s no longer needed.
    132   dispatch_queue_t serial_queue =
    133       dispatch_queue_create(DISPATCH_QUEUE_LABEL, DISPATCH_QUEUE_SERIAL);
    134   // Current used channel layout
    135   atomic<cubeb_channel_layout> layout{CUBEB_LAYOUT_UNDEFINED};
    136   uint32_t channels = 0;
    137 };
    138 
    139 @@ -181,29 +194,31 @@ to_string(io_side side)
    140   }
    141 }
    142 
    143 struct device_info {
    144   AudioDeviceID id = kAudioObjectUnknown;
    145   device_flags_value flags = DEV_UNKNOWN;
    146 };
    147 
    148 +#if !TARGET_OS_IPHONE
    149 struct property_listener {
    150   AudioDeviceID device_id;
    151   const AudioObjectPropertyAddress * property_address;
    152   AudioObjectPropertyListenerProc callback;
    153   cubeb_stream * stream;
    154 
    155   property_listener(AudioDeviceID id,
    156                     const AudioObjectPropertyAddress * address,
    157                     AudioObjectPropertyListenerProc proc, cubeb_stream * stm)
    158       : device_id(id), property_address(address), callback(proc), stream(stm)
    159   {
    160   }
    161 };
    162 +#endif
    163 
    164 struct cubeb_stream {
    165   explicit cubeb_stream(cubeb * context);
    166 
    167   /* Note: Must match cubeb_stream layout in cubeb.c. */
    168   cubeb * context;
    169   void * user_ptr = nullptr;
    170   /**/
    171 @@ -252,32 +267,36 @@ struct cubeb_stream {
    172   /* Latency requested by the user. */
    173   uint32_t latency_frames = 0;
    174   atomic<uint32_t> current_latency_frames{0};
    175   atomic<uint32_t> total_output_latency_frames{0};
    176   unique_ptr<cubeb_resampler, decltype(&cubeb_resampler_destroy)> resampler;
    177   /* This is true if a device change callback is currently running.  */
    178   atomic<bool> switching_device{false};
    179   atomic<bool> buffer_size_change_state{false};
    180 +  #if !TARGET_OS_IPHONE
    181   AudioDeviceID aggregate_device_id =
    182       kAudioObjectUnknown; // the aggregate device id
    183   AudioObjectID plugin_id =
    184       kAudioObjectUnknown; // used to create aggregate device
    185 +  #endif
    186   /* Mixer interface */
    187   unique_ptr<cubeb_mixer, decltype(&cubeb_mixer_destroy)> mixer;
    188   /* Buffer where remixing/resampling will occur when upmixing is required */
    189   /* Only accessed from callback thread */
    190   unique_ptr<uint8_t[]> temp_buffer;
    191   size_t temp_buffer_size = 0; // size in bytes.
    192 +  #if !TARGET_OS_IPHONE
    193   /* Listeners indicating what system events are monitored. */
    194   unique_ptr<property_listener> default_input_listener;
    195   unique_ptr<property_listener> default_output_listener;
    196   unique_ptr<property_listener> input_alive_listener;
    197   unique_ptr<property_listener> input_source_listener;
    198   unique_ptr<property_listener> output_source_listener;
    199 +  #endif
    200 };
    201 
    202 bool
    203 has_input(cubeb_stream * stm)
    204 {
    205   return stm->input_stream_params.rate != 0;
    206 }
    207 
    208 @@ -381,24 +400,16 @@ bool
    209 is_common_sample_rate(Float64 sample_rate)
    210 {
    211   /* Some commonly used sample rates and their multiples and divisors. */
    212   return sample_rate == 8000 || sample_rate == 16000 || sample_rate == 22050 ||
    213          sample_rate == 32000 || sample_rate == 44100 || sample_rate == 48000 ||
    214          sample_rate == 88200 || sample_rate == 96000;
    215 }
    216 
    217 -#if TARGET_OS_IPHONE
    218 -typedef UInt32 AudioDeviceID;
    219 -typedef UInt32 AudioObjectID;
    220 -
    221 -#define AudioGetCurrentHostTime mach_absolute_time
    222 -
    223 -#endif
    224 -
    225 uint64_t
    226 ConvertHostTimeToNanos(uint64_t host_time)
    227 {
    228   static struct mach_timebase_info timebase_info;
    229   static bool initialized = false;
    230   if (!initialized) {
    231     mach_timebase_info(&timebase_info);
    232     initialized = true;
    233 @@ -756,23 +767,23 @@ audiounit_init(cubeb ** context, char co
    234 }
    235 
    236 static char const *
    237 audiounit_get_backend_id(cubeb * /* ctx */)
    238 {
    239   return "audiounit";
    240 }
    241 
    242 -#if !TARGET_OS_IPHONE
    243 
    244 static int
    245 audiounit_stream_get_volume(cubeb_stream * stm, float * volume);
    246 static int
    247 audiounit_stream_set_volume(cubeb_stream * stm, float volume);
    248 
    249 +#if !TARGET_OS_IPHONE
    250 static int
    251 audiounit_set_device_info(cubeb_stream * stm, AudioDeviceID id, io_side side)
    252 {
    253   assert(stm);
    254 
    255   device_info * info = nullptr;
    256   cubeb_device_type type = CUBEB_DEVICE_TYPE_UNKNOWN;
    257 
    258 @@ -806,42 +817,47 @@ audiounit_set_device_info(cubeb_stream *
    259   }
    260 
    261   assert(info->id);
    262   assert(info->flags & DEV_INPUT && !(info->flags & DEV_OUTPUT) ||
    263          !(info->flags & DEV_INPUT) && info->flags & DEV_OUTPUT);
    264 
    265   return CUBEB_OK;
    266 }
    267 +#endif
    268 
    269 static int
    270 audiounit_reinit_stream(cubeb_stream * stm, device_flags_value flags)
    271 {
    272   auto_lock context_lock(stm->context->mutex);
    273   assert((flags & DEV_INPUT && stm->input_unit) ||
    274          (flags & DEV_OUTPUT && stm->output_unit));
    275   if (!stm->shutdown) {
    276     audiounit_stream_stop_internal(stm);
    277   }
    278 
    279 -  int r = audiounit_uninstall_device_changed_callback(stm);
    280 +  int r;
    281 +#if !TARGET_OS_IPHONE
    282 +  r = audiounit_uninstall_device_changed_callback(stm);
    283   if (r != CUBEB_OK) {
    284     LOG("(%p) Could not uninstall all device change listeners.", stm);
    285   }
    286 +#endif
    287 
    288   {
    289     auto_lock lock(stm->mutex);
    290     float volume = 0.0;
    291     int vol_rv = CUBEB_ERROR;
    292     if (stm->output_unit) {
    293       vol_rv = audiounit_stream_get_volume(stm, &volume);
    294     }
    295 
    296     audiounit_close_stream(stm);
    297 
    298 +    #if !TARGET_OS_IPHONE
    299     /* Reinit occurs in one of the following case:
    300      * - When the device is not alive any more
    301      * - When the default system device change.
    302      * - The bluetooth device changed from A2DP to/from HFP/HSP profile
    303      * We first attempt to re-use the same device id, should that fail we will
    304      * default to the (potentially new) default device. */
    305     AudioDeviceID input_device =
    306         flags & DEV_INPUT ? stm->input_device.id : kAudioObjectUnknown;
    307 @@ -861,29 +877,33 @@ audiounit_reinit_stream(cubeb_stream * s
    308     r = audiounit_set_device_info(stm, kAudioObjectUnknown, io_side::OUTPUT);
    309     if (r != CUBEB_OK) {
    310       LOG("(%p) Set output device info failed. This can happen when last media "
    311           "device is unplugged",
    312           stm);
    313       return CUBEB_ERROR;
    314     }
    315 
    316 +    #endif
    317 +
    318     if (audiounit_setup_stream(stm) != CUBEB_OK) {
    319       LOG("(%p) Stream reinit failed.", stm);
    320 +      #if !TARGET_OS_IPHONE
    321       if (flags & DEV_INPUT && input_device != kAudioObjectUnknown) {
    322         // Attempt to re-use the same device-id failed, so attempt again with
    323         // default input device.
    324         audiounit_close_stream(stm);
    325         if (audiounit_set_device_info(stm, kAudioObjectUnknown,
    326                                       io_side::INPUT) != CUBEB_OK ||
    327             audiounit_setup_stream(stm) != CUBEB_OK) {
    328           LOG("(%p) Second stream reinit failed.", stm);
    329           return CUBEB_ERROR;
    330         }
    331       }
    332 +      #endif
    333     }
    334 
    335     if (vol_rv == CUBEB_OK) {
    336       audiounit_stream_set_volume(stm, volume);
    337     }
    338 
    339     // If the stream was running, start it again.
    340     if (!stm->shutdown) {
    341 @@ -909,27 +929,30 @@ audiounit_reinit_stream_async(cubeb_stre
    342   // Get/SetProperties method from inside notify callback
    343   dispatch_async(stm->context->serial_queue, ^() {
    344     if (stm->destroy_pending) {
    345       ALOG("(%p) stream pending destroy, cancelling reinit task", stm);
    346       return;
    347     }
    348 
    349     if (audiounit_reinit_stream(stm, flags) != CUBEB_OK) {
    350 +      #if !TARGET_OS_IPHONE
    351       if (audiounit_uninstall_system_changed_callback(stm) != CUBEB_OK) {
    352         LOG("(%p) Could not uninstall system changed callback", stm);
    353       }
    354 +      #endif
    355       stm->state_callback(stm, stm->user_ptr, CUBEB_STATE_ERROR);
    356       LOG("(%p) Could not reopen the stream after switching.", stm);
    357     }
    358     stm->switching_device = false;
    359     stm->reinit_pending = false;
    360   });
    361 }
    362 
    363 +#if !TARGET_OS_IPHONE
    364 static char const *
    365 event_addr_to_string(AudioObjectPropertySelector selector)
    366 {
    367   switch (selector) {
    368   case kAudioHardwarePropertyDefaultOutputDevice:
    369     return "kAudioHardwarePropertyDefaultOutputDevice";
    370   case kAudioHardwarePropertyDefaultInputDevice:
    371     return "kAudioHardwarePropertyDefaultInputDevice";
    372 @@ -1091,16 +1114,17 @@ audiounit_install_device_changed_callbac
    373           rv, stm->input_device.id);
    374       r = CUBEB_ERROR;
    375     }
    376   }
    377 
    378   return r;
    379 }
    380 
    381 +#if !TARGET_OS_IPHONE
    382 static int
    383 audiounit_install_system_changed_callback(cubeb_stream * stm)
    384 {
    385   OSStatus r;
    386 
    387   if (stm->output_unit) {
    388     /* This event will notify us when the default audio device changes,
    389      * for example when the user plugs in a USB headset and the system chooses
    390 @@ -1131,16 +1155,17 @@ audiounit_install_system_changed_callbac
    391           "kAudioHardwarePropertyDefaultInputDevice rv=%d",
    392           r);
    393       return CUBEB_ERROR;
    394     }
    395   }
    396 
    397   return CUBEB_OK;
    398 }
    399 +#endif
    400 
    401 static int
    402 audiounit_uninstall_device_changed_callback(cubeb_stream * stm)
    403 {
    404   OSStatus rv;
    405   // Failing to uninstall listeners is not a fatal error.
    406   int r = CUBEB_OK;
    407 
    408 @@ -1207,17 +1232,17 @@ audiounit_uninstall_system_changed_callb
    409 static int
    410 audiounit_get_acceptable_latency_range(AudioValueRange * latency_range)
    411 {
    412   UInt32 size;
    413   OSStatus r;
    414   AudioDeviceID output_device_id;
    415   AudioObjectPropertyAddress output_device_buffer_size_range = {
    416       kAudioDevicePropertyBufferFrameSizeRange, kAudioDevicePropertyScopeOutput,
    417 -      kAudioObjectPropertyElementMaster};
    418 +      kAudioObjectPropertyElementMain};
    419 
    420   output_device_id = audiounit_get_default_device_id(CUBEB_DEVICE_TYPE_OUTPUT);
    421   if (output_device_id == kAudioObjectUnknown) {
    422     LOG("Could not get default output device id.");
    423     return CUBEB_ERROR;
    424   }
    425 
    426   /* Get the buffer size range this device supports */
    427 @@ -1228,17 +1253,16 @@ audiounit_get_acceptable_latency_range(A
    428                                  &size, latency_range);
    429   if (r != noErr) {
    430     LOG("AudioObjectGetPropertyData/buffer size range rv=%d", r);
    431     return CUBEB_ERROR;
    432   }
    433 
    434   return CUBEB_OK;
    435 }
    436 -#endif /* !TARGET_OS_IPHONE */
    437 
    438 static AudioObjectID
    439 audiounit_get_default_device_id(cubeb_device_type type)
    440 {
    441   const AudioObjectPropertyAddress * adr;
    442   if (type == CUBEB_DEVICE_TYPE_OUTPUT) {
    443     adr = &DEFAULT_OUTPUT_DEVICE_PROPERTY_ADDRESS;
    444   } else if (type == CUBEB_DEVICE_TYPE_INPUT) {
    445 @@ -1251,31 +1275,32 @@ audiounit_get_default_device_id(cubeb_de
    446   UInt32 size = sizeof(AudioDeviceID);
    447   if (AudioObjectGetPropertyData(kAudioObjectSystemObject, adr, 0, NULL, &size,
    448                                  &devid) != noErr) {
    449     return kAudioObjectUnknown;
    450   }
    451 
    452   return devid;
    453 }
    454 +#endif /* !TARGET_OS_IPHONE */
    455 
    456 int
    457 audiounit_get_max_channel_count(cubeb * ctx, uint32_t * max_channels)
    458 {
    459 #if TARGET_OS_IPHONE
    460   // TODO: [[AVAudioSession sharedInstance] maximumOutputNumberOfChannels]
    461   *max_channels = 2;
    462 #else
    463   UInt32 size;
    464   OSStatus r;
    465   AudioDeviceID output_device_id;
    466   AudioStreamBasicDescription stream_format;
    467   AudioObjectPropertyAddress stream_format_address = {
    468       kAudioDevicePropertyStreamFormat, kAudioDevicePropertyScopeOutput,
    469 -      kAudioObjectPropertyElementMaster};
    470 +      kAudioObjectPropertyElementMain};
    471 
    472   assert(ctx && max_channels);
    473 
    474   output_device_id = audiounit_get_default_device_id(CUBEB_DEVICE_TYPE_OUTPUT);
    475   if (output_device_id == kAudioObjectUnknown) {
    476     return CUBEB_ERROR;
    477   }
    478 
    479 @@ -1304,52 +1329,52 @@ audiounit_get_min_latency(cubeb * /* ctx
    480   AudioValueRange latency_range;
    481   if (audiounit_get_acceptable_latency_range(&latency_range) != CUBEB_OK) {
    482     LOG("Could not get acceptable latency range.");
    483     return CUBEB_ERROR;
    484   }
    485 
    486   *latency_frames =
    487       max<uint32_t>(latency_range.mMinimum, SAFE_MIN_LATENCY_FRAMES);
    488 +  return CUBEB_OK;
    489 #endif
    490 -
    491 -  return CUBEB_OK;
    492 }
    493 
    494 static int
    495 audiounit_get_preferred_sample_rate(cubeb * /* ctx */, uint32_t * rate)
    496 {
    497 #if TARGET_OS_IPHONE
    498 -  // TODO
    499 -  return CUBEB_ERROR_NOT_SUPPORTED;
    500 +  *rate = 44100;
    501 +  return CUBEB_OK;
    502 #else
    503   UInt32 size;
    504   OSStatus r;
    505   Float64 fsamplerate;
    506   AudioDeviceID output_device_id;
    507   AudioObjectPropertyAddress samplerate_address = {
    508       kAudioDevicePropertyNominalSampleRate, kAudioObjectPropertyScopeGlobal,
    509 -      kAudioObjectPropertyElementMaster};
    510 +      kAudioObjectPropertyElementMain};
    511 
    512   output_device_id = audiounit_get_default_device_id(CUBEB_DEVICE_TYPE_OUTPUT);
    513   if (output_device_id == kAudioObjectUnknown) {
    514     return CUBEB_ERROR;
    515   }
    516 
    517   size = sizeof(fsamplerate);
    518   r = AudioObjectGetPropertyData(output_device_id, &samplerate_address, 0, NULL,
    519                                  &size, &fsamplerate);
    520 
    521   if (r != noErr) {
    522     return CUBEB_ERROR;
    523   }
    524 
    525   *rate = static_cast<uint32_t>(fsamplerate);
    526 +
    527 +  return CUBEB_OK;
    528 #endif
    529 -  return CUBEB_OK;
    530 }
    531 
    532 static cubeb_channel_layout
    533 audiounit_convert_channel_layout(AudioChannelLayout * layout)
    534 {
    535   // When having one or two channel, force mono or stereo. Some devices (namely,
    536   // Bose QC35, mark 1 and 2), expose a single channel mapped to the right for
    537   // some reason.
    538 @@ -1380,16 +1405,19 @@ audiounit_convert_channel_layout(AudioCh
    539   }
    540 
    541   return cl;
    542 }
    543 
    544 static cubeb_channel_layout
    545 audiounit_get_preferred_channel_layout(AudioUnit output_unit)
    546 {
    547 +  #if TARGET_OS_IPHONE
    548 +    return CUBEB_LAYOUT_STEREO;
    549 +  #else
    550   OSStatus rv = noErr;
    551   UInt32 size = 0;
    552   rv = AudioUnitGetPropertyInfo(
    553       output_unit, kAudioDevicePropertyPreferredChannelLayout,
    554       kAudioUnitScope_Output, AU_OUT_BUS, &size, nullptr);
    555   if (rv != noErr) {
    556     LOG("AudioUnitGetPropertyInfo/kAudioDevicePropertyPreferredChannelLayout "
    557         "rv=%d",
    558 @@ -1404,16 +1432,17 @@ audiounit_get_preferred_channel_layout(A
    559       kAudioUnitScope_Output, AU_OUT_BUS, layout.get(), &size);
    560   if (rv != noErr) {
    561     LOG("AudioUnitGetProperty/kAudioDevicePropertyPreferredChannelLayout rv=%d",
    562         rv);
    563     return CUBEB_LAYOUT_UNDEFINED;
    564   }
    565 
    566   return audiounit_convert_channel_layout(layout.get());
    567 +  #endif
    568 }
    569 
    570 static cubeb_channel_layout
    571 audiounit_get_current_channel_layout(AudioUnit output_unit)
    572 {
    573   OSStatus rv = noErr;
    574   UInt32 size = 0;
    575   rv = AudioUnitGetPropertyInfo(
    576 @@ -1437,18 +1466,20 @@ audiounit_get_current_channel_layout(Aud
    577   }
    578 
    579   return audiounit_convert_channel_layout(layout.get());
    580 }
    581 
    582 static int
    583 audiounit_create_unit(AudioUnit * unit, device_info * device);
    584 
    585 +#if !TARGET_OS_IPHONE
    586 static OSStatus
    587 audiounit_remove_device_listener(cubeb * context, cubeb_device_type devtype);
    588 +#endif
    589 
    590 static void
    591 audiounit_destroy(cubeb * ctx)
    592 {
    593   {
    594     auto_lock lock(ctx->mutex);
    595 
    596     // Disabling this assert for bug 1083664 -- we seem to leak a stream
    597 @@ -1460,23 +1491,25 @@ audiounit_destroy(cubeb * ctx)
    598 
    599     // Destroying a cubeb context with device collection callbacks registered
    600     // is misuse of the API, assert then attempt to clean up.
    601     assert(!ctx->input_collection_changed_callback &&
    602            !ctx->input_collection_changed_user_ptr &&
    603            !ctx->output_collection_changed_callback &&
    604            !ctx->output_collection_changed_user_ptr);
    605 
    606 +    #if !TARGET_OS_IPHONE
    607     /* Unregister the callback if necessary. */
    608     if (ctx->input_collection_changed_callback) {
    609       audiounit_remove_device_listener(ctx, CUBEB_DEVICE_TYPE_INPUT);
    610     }
    611     if (ctx->output_collection_changed_callback) {
    612       audiounit_remove_device_listener(ctx, CUBEB_DEVICE_TYPE_OUTPUT);
    613     }
    614 +    #endif
    615   }
    616 
    617   dispatch_release(ctx->serial_queue);
    618 
    619   delete ctx;
    620 }
    621 
    622 static void
    623 @@ -1594,23 +1627,24 @@ audiounit_layout_init(cubeb_stream * stm
    624   }
    625 
    626   stm->context->layout = audiounit_get_current_channel_layout(stm->output_unit);
    627 
    628   audiounit_set_channel_layout(stm->output_unit, io_side::OUTPUT,
    629                                stm->context->layout);
    630 }
    631 
    632 +#if !TARGET_OS_IPHONE
    633 static vector<AudioObjectID>
    634 audiounit_get_sub_devices(AudioDeviceID device_id)
    635 {
    636   vector<AudioDeviceID> sub_devices;
    637   AudioObjectPropertyAddress property_address = {
    638       kAudioAggregateDevicePropertyActiveSubDeviceList,
    639 -      kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster};
    640 +      kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMain};
    641   UInt32 size = 0;
    642   OSStatus rv = AudioObjectGetPropertyDataSize(device_id, &property_address, 0,
    643                                                nullptr, &size);
    644 
    645   if (rv != noErr) {
    646     sub_devices.push_back(device_id);
    647     return sub_devices;
    648   }
    649 @@ -1629,17 +1663,17 @@ audiounit_get_sub_devices(AudioDeviceID 
    650 }
    651 
    652 static int
    653 audiounit_create_blank_aggregate_device(AudioObjectID * plugin_id,
    654                                         AudioDeviceID * aggregate_device_id)
    655 {
    656   AudioObjectPropertyAddress address_plugin_bundle_id = {
    657       kAudioHardwarePropertyPlugInForBundleID, kAudioObjectPropertyScopeGlobal,
    658 -      kAudioObjectPropertyElementMaster};
    659 +      kAudioObjectPropertyElementMain};
    660   UInt32 size = 0;
    661   OSStatus r = AudioObjectGetPropertyDataSize(
    662       kAudioObjectSystemObject, &address_plugin_bundle_id, 0, NULL, &size);
    663   if (r != noErr) {
    664     LOG("AudioObjectGetPropertyDataSize/"
    665         "kAudioHardwarePropertyPlugInForBundleID, rv=%d",
    666         r);
    667     return CUBEB_ERROR;
    668 @@ -1659,17 +1693,17 @@ audiounit_create_blank_aggregate_device(
    669     LOG("AudioObjectGetPropertyData/kAudioHardwarePropertyPlugInForBundleID, "
    670         "rv=%d",
    671         r);
    672     return CUBEB_ERROR;
    673   }
    674 
    675   AudioObjectPropertyAddress create_aggregate_device_address = {
    676       kAudioPlugInCreateAggregateDevice, kAudioObjectPropertyScopeGlobal,
    677 -      kAudioObjectPropertyElementMaster};
    678 +      kAudioObjectPropertyElementMain};
    679   r = AudioObjectGetPropertyDataSize(
    680       *plugin_id, &create_aggregate_device_address, 0, nullptr, &size);
    681   if (r != noErr) {
    682     LOG("AudioObjectGetPropertyDataSize/kAudioPlugInCreateAggregateDevice, "
    683         "rv=%d",
    684         r);
    685     return CUBEB_ERROR;
    686   }
    687 @@ -1731,17 +1765,17 @@ audiounit_create_blank_aggregate_device(
    688 // object is increased.
    689 static CFStringRef
    690 get_device_name(AudioDeviceID id)
    691 {
    692   UInt32 size = sizeof(CFStringRef);
    693   CFStringRef UIname = nullptr;
    694   AudioObjectPropertyAddress address_uuid = {kAudioDevicePropertyDeviceUID,
    695                                              kAudioObjectPropertyScopeGlobal,
    696 -                                             kAudioObjectPropertyElementMaster};
    697 +                                             kAudioObjectPropertyElementMain};
    698   OSStatus err =
    699       AudioObjectGetPropertyData(id, &address_uuid, 0, nullptr, &size, &UIname);
    700   return (err == noErr) ? UIname : NULL;
    701 }
    702 
    703 static int
    704 audiounit_set_aggregate_sub_device_list(AudioDeviceID aggregate_device_id,
    705                                         AudioDeviceID input_device_id,
    706 @@ -1774,17 +1808,17 @@ audiounit_set_aggregate_sub_device_list(
    707       return CUBEB_ERROR;
    708     }
    709     CFArrayAppendValue(aggregate_sub_devices_array, ref);
    710     CFRelease(ref);
    711   }
    712 
    713   AudioObjectPropertyAddress aggregate_sub_device_list = {
    714       kAudioAggregateDevicePropertyFullSubDeviceList,
    715 -      kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster};
    716 +      kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMain};
    717   UInt32 size = sizeof(CFMutableArrayRef);
    718   OSStatus rv = AudioObjectSetPropertyData(
    719       aggregate_device_id, &aggregate_sub_device_list, 0, nullptr, size,
    720       &aggregate_sub_devices_array);
    721   CFRelease(aggregate_sub_devices_array);
    722   if (rv != noErr) {
    723     LOG("AudioObjectSetPropertyData/"
    724         "kAudioAggregateDevicePropertyFullSubDeviceList, rv=%d",
    725 @@ -1796,17 +1830,17 @@ audiounit_set_aggregate_sub_device_list(
    726 }
    727 
    728 static int
    729 audiounit_set_master_aggregate_device(const AudioDeviceID aggregate_device_id)
    730 {
    731   assert(aggregate_device_id != kAudioObjectUnknown);
    732   AudioObjectPropertyAddress master_aggregate_sub_device = {
    733       kAudioAggregateDevicePropertyMasterSubDevice,
    734 -      kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster};
    735 +      kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMain};
    736 
    737   // Master become the 1st output sub device
    738   AudioDeviceID output_device_id =
    739       audiounit_get_default_device_id(CUBEB_DEVICE_TYPE_OUTPUT);
    740   const vector<AudioDeviceID> output_sub_devices =
    741       audiounit_get_sub_devices(output_device_id);
    742   CFStringRef master_sub_device = get_device_name(output_sub_devices[0]);
    743 
    744 @@ -1829,17 +1863,17 @@ audiounit_set_master_aggregate_device(co
    745 
    746 static int
    747 audiounit_activate_clock_drift_compensation(
    748     const AudioDeviceID aggregate_device_id)
    749 {
    750   assert(aggregate_device_id != kAudioObjectUnknown);
    751   AudioObjectPropertyAddress address_owned = {
    752       kAudioObjectPropertyOwnedObjects, kAudioObjectPropertyScopeGlobal,
    753 -      kAudioObjectPropertyElementMaster};
    754 +      kAudioObjectPropertyElementMain};
    755 
    756   UInt32 qualifier_data_size = sizeof(AudioObjectID);
    757   AudioClassID class_id = kAudioSubDeviceClassID;
    758   void * qualifier_data = &class_id;
    759   UInt32 size = 0;
    760   OSStatus rv = AudioObjectGetPropertyDataSize(
    761       aggregate_device_id, &address_owned, qualifier_data_size, qualifier_data,
    762       &size);
    763 @@ -1861,17 +1895,17 @@ audiounit_activate_clock_drift_compensat
    764   if (rv != noErr) {
    765     LOG("AudioObjectGetPropertyData/kAudioObjectPropertyOwnedObjects, rv=%d",
    766         rv);
    767     return CUBEB_ERROR;
    768   }
    769 
    770   AudioObjectPropertyAddress address_drift = {
    771       kAudioSubDevicePropertyDriftCompensation, kAudioObjectPropertyScopeGlobal,
    772 -      kAudioObjectPropertyElementMaster};
    773 +      kAudioObjectPropertyElementMain};
    774 
    775   // Start from the second device since the first is the master clock
    776   for (UInt32 i = 1; i < subdevices_num; ++i) {
    777     UInt32 drift_compensation_value = 1;
    778     rv = AudioObjectSetPropertyData(sub_devices[i], &address_drift, 0, nullptr,
    779                                     sizeof(UInt32), &drift_compensation_value);
    780     if (rv != noErr) {
    781       LOG("AudioObjectSetPropertyData/"
    782 @@ -1930,17 +1964,17 @@ audiounit_workaround_for_airpod(cubeb_st
    783         &output_min_rate, &output_max_rate, &output_nominal_rate);
    784     LOG("(%p) Output device %u, name: %s, min: %u, max: %u, nominal rate: %u",
    785         stm, stm->output_device.id, output_device_info.friendly_name,
    786         output_min_rate, output_max_rate, output_nominal_rate);
    787 
    788     Float64 rate = input_nominal_rate;
    789     AudioObjectPropertyAddress addr = {kAudioDevicePropertyNominalSampleRate,
    790                                        kAudioObjectPropertyScopeGlobal,
    791 -                                       kAudioObjectPropertyElementMaster};
    792 +                                       kAudioObjectPropertyElementMain};
    793 
    794     OSStatus rv = AudioObjectSetPropertyData(stm->aggregate_device_id, &addr, 0,
    795                                              nullptr, sizeof(Float64), &rate);
    796     if (rv != noErr) {
    797       LOG("Non fatal error, "
    798           "AudioObjectSetPropertyData/kAudioDevicePropertyNominalSampleRate, "
    799           "rv=%d",
    800           rv);
    801 @@ -2014,17 +2048,17 @@ audiounit_create_aggregate_device(cubeb_
    802 static int
    803 audiounit_destroy_aggregate_device(AudioObjectID plugin_id,
    804                                    AudioDeviceID * aggregate_device_id)
    805 {
    806   assert(aggregate_device_id && *aggregate_device_id != kAudioDeviceUnknown &&
    807          plugin_id != kAudioObjectUnknown);
    808   AudioObjectPropertyAddress destroy_aggregate_device_addr = {
    809       kAudioPlugInDestroyAggregateDevice, kAudioObjectPropertyScopeGlobal,
    810 -      kAudioObjectPropertyElementMaster};
    811 +      kAudioObjectPropertyElementMain};
    812   UInt32 size;
    813   OSStatus rv = AudioObjectGetPropertyDataSize(
    814       plugin_id, &destroy_aggregate_device_addr, 0, NULL, &size);
    815   if (rv != noErr) {
    816     LOG("AudioObjectGetPropertyDataSize/kAudioPlugInDestroyAggregateDevice, "
    817         "rv=%d",
    818         rv);
    819     return CUBEB_ERROR;
    820 @@ -2037,16 +2071,17 @@ audiounit_destroy_aggregate_device(Audio
    821         rv);
    822     return CUBEB_ERROR;
    823   }
    824 
    825   LOG("Destroyed aggregate device %d", *aggregate_device_id);
    826   *aggregate_device_id = kAudioObjectUnknown;
    827   return CUBEB_OK;
    828 }
    829 +#endif
    830 
    831 static int
    832 audiounit_new_unit_instance(AudioUnit * unit, device_info * device)
    833 {
    834   AudioComponentDescription desc;
    835   AudioComponent comp;
    836   OSStatus rv;
    837 
    838 @@ -2173,16 +2208,19 @@ audiounit_init_input_linear_buffer(cubeb
    839   assert(stream->input_linear_buffer->length() == 0);
    840 
    841   return CUBEB_OK;
    842 }
    843 
    844 static uint32_t
    845 audiounit_clamp_latency(cubeb_stream * stm, uint32_t latency_frames)
    846 {
    847 +  #if TARGET_OS_IPHONE
    848 +  return latency_frames;
    849 +  #else
    850   // For the 1st stream set anything within safe min-max
    851   assert(audiounit_active_streams(stm->context) > 0);
    852   if (audiounit_active_streams(stm->context) == 1) {
    853     return max(min<uint32_t>(latency_frames, SAFE_MAX_LATENCY_FRAMES),
    854                SAFE_MIN_LATENCY_FRAMES);
    855   }
    856   assert(stm->output_unit);
    857 
    858 @@ -2233,18 +2271,20 @@ audiounit_clamp_latency(cubeb_stream * s
    859   } else if (output_buffer_size != 0) {
    860     upper_latency_limit = output_buffer_size;
    861   } else {
    862     upper_latency_limit = SAFE_MAX_LATENCY_FRAMES;
    863   }
    864 
    865   return max(min<uint32_t>(latency_frames, upper_latency_limit),
    866              SAFE_MIN_LATENCY_FRAMES);
    867 +  #endif
    868 }
    869 
    870 +#if !TARGET_OS_IPHONE
    871 /*
    872  * Change buffer size is prone to deadlock thus we change it
    873  * following the steps:
    874  * - register a listener for the buffer size property
    875  * - change the property
    876  * - wait until the listener is executed
    877  * - property has changed, remove the listener
    878  * */
    879 @@ -2285,21 +2325,25 @@ buffer_size_changed_callback(void * inCl
    880           "= %d for scope %d",
    881           stm, au_type, new_buffer_size, inScope);
    882     }
    883     stm->buffer_size_change_state = true;
    884     break;
    885   }
    886   }
    887 }
    888 +#endif
    889 
    890 static int
    891 audiounit_set_buffer_size(cubeb_stream * stm, uint32_t new_size_frames,
    892                           io_side side)
    893 {
    894 +  #if TARGET_OS_IPHONE
    895 +  return CUBEB_OK;
    896 +  #else
    897   AudioUnit au = stm->output_unit;
    898   AudioUnitScope au_scope = kAudioUnitScope_Input;
    899   AudioUnitElement au_element = AU_OUT_BUS;
    900 
    901   if (side == io_side::INPUT) {
    902     au = stm->input_unit;
    903     au_scope = kAudioUnitScope_Output;
    904     au_element = AU_IN_BUS;
    905 @@ -2377,16 +2421,17 @@ audiounit_set_buffer_size(cubeb_stream *
    906   if (!stm->buffer_size_change_state && count >= 30) {
    907     LOG("(%p) Error, did not get buffer size change callback ...", stm);
    908     return CUBEB_ERROR;
    909   }
    910 
    911   LOG("(%p) %s buffer size changed to %u frames.", stm, to_string(side),
    912       new_size_frames);
    913   return CUBEB_OK;
    914 +  #endif
    915 }
    916 
    917 static int
    918 audiounit_configure_input(cubeb_stream * stm)
    919 {
    920   assert(stm && stm->input_unit);
    921 
    922   int r = 0;
    923 @@ -2593,16 +2638,17 @@ audiounit_setup_stream(cubeb_stream * st
    924     return CUBEB_ERROR_NOT_SUPPORTED;
    925   }
    926 
    927   int r = 0;
    928 
    929   device_info in_dev_info = stm->input_device;
    930   device_info out_dev_info = stm->output_device;
    931 
    932 +  #if !TARGET_OS_IPHONE
    933   if (has_input(stm) && has_output(stm) &&
    934       stm->input_device.id != stm->output_device.id) {
    935     r = audiounit_create_aggregate_device(stm);
    936     if (r != CUBEB_OK) {
    937       stm->aggregate_device_id = kAudioObjectUnknown;
    938       LOG("(%p) Create aggregate devices failed.", stm);
    939       // !!!NOTE: It is not necessary to return here. If it does not
    940       // return it will fallback to the old implementation. The intention
    941 @@ -2610,16 +2656,20 @@ audiounit_setup_stream(cubeb_stream * st
    942       // it after a couple of weeks.
    943       return r;
    944     } else {
    945       in_dev_info.id = out_dev_info.id = stm->aggregate_device_id;
    946       in_dev_info.flags = DEV_INPUT;
    947       out_dev_info.flags = DEV_OUTPUT;
    948     }
    949   }
    950 +  #else
    951 +  in_dev_info.flags = DEV_SYSTEM_DEFAULT | DEV_INPUT;
    952 +  out_dev_info.flags = DEV_SYSTEM_DEFAULT | DEV_OUTPUT;
    953 +  #endif
    954 
    955   if (has_input(stm)) {
    956     r = audiounit_create_unit(&stm->input_unit, &in_dev_info);
    957     if (r != CUBEB_OK) {
    958       LOG("(%p) AudioUnit creation for input failed.", stm);
    959       return r;
    960     }
    961   }
    962 @@ -2751,18 +2801,20 @@ audiounit_setup_stream(cubeb_stream * st
    963 
    964   if (stm->output_unit != NULL) {
    965     r = AudioUnitInitialize(stm->output_unit);
    966     if (r != noErr) {
    967       LOG("AudioUnitInitialize/output rv=%d", r);
    968       return CUBEB_ERROR;
    969     }
    970 
    971 +    #if !TARGET_OS_IPHONE
    972     stm->current_latency_frames = audiounit_get_device_presentation_latency(
    973         stm->output_device.id, kAudioDevicePropertyScopeOutput);
    974 +    #endif
    975 
    976     Float64 unit_s;
    977     UInt32 size = sizeof(unit_s);
    978     if (AudioUnitGetProperty(stm->output_unit, kAudioUnitProperty_Latency,
    979                              kAudioUnitScope_Global, 0, &unit_s,
    980                              &size) == noErr) {
    981       stm->current_latency_frames +=
    982           static_cast<uint32_t>(unit_s * stm->output_desc.mSampleRate);
    983 @@ -2772,20 +2824,22 @@ audiounit_setup_stream(cubeb_stream * st
    984   if (stm->input_unit && stm->output_unit) {
    985     // According to the I/O hardware rate it is expected a specific pattern of
    986     // callbacks for example is input is 44100 and output is 48000 we expected
    987     // no more than 2 out callback in a row.
    988     stm->expected_output_callbacks_in_a_row =
    989         ceilf(stm->output_hw_rate / stm->input_hw_rate);
    990   }
    991 
    992 +  #if !TARGET_OS_IPHONE
    993   r = audiounit_install_device_changed_callback(stm);
    994   if (r != CUBEB_OK) {
    995     LOG("(%p) Could not install all device change callback.", stm);
    996   }
    997 +  #endif
    998 
    999   return CUBEB_OK;
   1000 }
   1001 
   1002 cubeb_stream::cubeb_stream(cubeb * context)
   1003     : context(context), resampler(nullptr, cubeb_resampler_destroy),
   1004       mixer(nullptr, cubeb_mixer_destroy)
   1005 {
   1006 @@ -2823,51 +2877,57 @@ audiounit_stream_init(cubeb * context, c
   1007   stm->latency_frames = latency_frames;
   1008 
   1009   if ((input_device && !input_stream_params) ||
   1010       (output_device && !output_stream_params)) {
   1011     return CUBEB_ERROR_INVALID_PARAMETER;
   1012   }
   1013   if (input_stream_params) {
   1014     stm->input_stream_params = *input_stream_params;
   1015 +  #if !TARGET_OS_IPHONE
   1016     r = audiounit_set_device_info(
   1017         stm.get(), reinterpret_cast<uintptr_t>(input_device), io_side::INPUT);
   1018     if (r != CUBEB_OK) {
   1019       LOG("(%p) Fail to set device info for input.", stm.get());
   1020       return r;
   1021     }
   1022 +  #endif
   1023   }
   1024   if (output_stream_params) {
   1025     stm->output_stream_params = *output_stream_params;
   1026 +  #if !TARGET_OS_IPHONE
   1027     r = audiounit_set_device_info(
   1028         stm.get(), reinterpret_cast<uintptr_t>(output_device), io_side::OUTPUT);
   1029     if (r != CUBEB_OK) {
   1030       LOG("(%p) Fail to set device info for output.", stm.get());
   1031       return r;
   1032     }
   1033 +  #endif
   1034   }
   1035 
   1036   {
   1037     // It's not critical to lock here, because no other thread has been started
   1038     // yet, but it allows to assert that the lock has been taken in
   1039     // `audiounit_setup_stream`.
   1040     auto_lock lock(stm->mutex);
   1041     r = audiounit_setup_stream(stm.get());
   1042   }
   1043 
   1044   if (r != CUBEB_OK) {
   1045     LOG("(%p) Could not setup the audiounit stream.", stm.get());
   1046     return r;
   1047   }
   1048 
   1049 +  #if !TARGET_OS_IPHONE
   1050   r = audiounit_install_system_changed_callback(stm.get());
   1051   if (r != CUBEB_OK) {
   1052     LOG("(%p) Could not install the device change callback.", stm.get());
   1053     return r;
   1054   }
   1055 +  #endif
   1056 
   1057   *stream = stm.release();
   1058   LOG("(%p) Cubeb stream init successful.", *stream);
   1059   return CUBEB_OK;
   1060 }
   1061 
   1062 static void
   1063 audiounit_close_stream(cubeb_stream * stm)
   1064 @@ -2886,54 +2946,60 @@ audiounit_close_stream(cubeb_stream * st
   1065     AudioUnitUninitialize(stm->output_unit);
   1066     AudioComponentInstanceDispose(stm->output_unit);
   1067     stm->output_unit = nullptr;
   1068   }
   1069 
   1070   stm->resampler.reset();
   1071   stm->mixer.reset();
   1072 
   1073 +  #if !TARGET_OS_IPHONE
   1074   if (stm->aggregate_device_id != kAudioObjectUnknown) {
   1075     audiounit_destroy_aggregate_device(stm->plugin_id,
   1076                                        &stm->aggregate_device_id);
   1077     stm->aggregate_device_id = kAudioObjectUnknown;
   1078   }
   1079 +  #endif
   1080 }
   1081 
   1082 static void
   1083 audiounit_stream_destroy_internal(cubeb_stream * stm)
   1084 {
   1085   stm->context->mutex.assert_current_thread_owns();
   1086 
   1087 +#if !TARGET_OS_IPHONE
   1088   int r = audiounit_uninstall_system_changed_callback(stm);
   1089   if (r != CUBEB_OK) {
   1090     LOG("(%p) Could not uninstall the device changed callback", stm);
   1091   }
   1092   r = audiounit_uninstall_device_changed_callback(stm);
   1093   if (r != CUBEB_OK) {
   1094     LOG("(%p) Could not uninstall all device change listeners", stm);
   1095   }
   1096 +#endif
   1097 
   1098   auto_lock lock(stm->mutex);
   1099   audiounit_close_stream(stm);
   1100   assert(audiounit_active_streams(stm->context) >= 1);
   1101   audiounit_decrement_active_streams(stm->context);
   1102 }
   1103 
   1104 static void
   1105 audiounit_stream_destroy(cubeb_stream * stm)
   1106 {
   1107 +  #if !TARGET_OS_IPHONE
   1108   int r = audiounit_uninstall_system_changed_callback(stm);
   1109   if (r != CUBEB_OK) {
   1110     LOG("(%p) Could not uninstall the device changed callback", stm);
   1111   }
   1112   r = audiounit_uninstall_device_changed_callback(stm);
   1113   if (r != CUBEB_OK) {
   1114     LOG("(%p) Could not uninstall all device change listeners", stm);
   1115   }
   1116 +  #endif
   1117 
   1118   if (!stm->shutdown.load()) {
   1119     auto_lock context_lock(stm->context->mutex);
   1120     audiounit_stream_stop_internal(stm);
   1121     stm->shutdown = true;
   1122   }
   1123 
   1124   stm->destroy_pending = true;
   1125 @@ -3081,16 +3147,17 @@ convert_uint32_into_string(UInt32 data)
   1126   // Reverse 0xWXYZ into 0xZYXW.
   1127   str[0] = (char)(data >> 24);
   1128   str[1] = (char)(data >> 16);
   1129   str[2] = (char)(data >> 8);
   1130   str[3] = (char)(data);
   1131   return str;
   1132 }
   1133 
   1134 +#if !TARGET_OS_IPHONE
   1135 int
   1136 audiounit_get_default_device_datasource(cubeb_device_type type, UInt32 * data)
   1137 {
   1138   AudioDeviceID id = audiounit_get_default_device_id(type);
   1139   if (id == kAudioObjectUnknown) {
   1140     return CUBEB_ERROR;
   1141   }
   1142 
   1143 @@ -3102,38 +3169,43 @@ audiounit_get_default_device_datasource(
   1144                                       : &OUTPUT_DATA_SOURCE_PROPERTY_ADDRESS,
   1145       0, NULL, &size, data);
   1146   if (r != noErr) {
   1147     *data = 0;
   1148   }
   1149 
   1150   return CUBEB_OK;
   1151 }
   1152 +#endif
   1153 
   1154 int
   1155 audiounit_get_default_device_name(cubeb_stream * stm,
   1156                                   cubeb_device * const device,
   1157                                   cubeb_device_type type)
   1158 {
   1159 +#if TARGET_OS_IPHONE
   1160 +  return CUBEB_ERROR_NOT_SUPPORTED;
   1161 +#else
   1162   assert(stm);
   1163   assert(device);
   1164 
   1165   UInt32 data;
   1166   int r = audiounit_get_default_device_datasource(type, &data);
   1167   if (r != CUBEB_OK) {
   1168     return r;
   1169   }
   1170   char ** name = type == CUBEB_DEVICE_TYPE_INPUT ? &device->input_name
   1171                                                  : &device->output_name;
   1172   *name = convert_uint32_into_string(data).release();
   1173   if (!strlen(*name)) { // empty string.
   1174     LOG("(%p) name of %s device is empty!", stm,
   1175         type == CUBEB_DEVICE_TYPE_INPUT ? "input" : "output");
   1176   }
   1177   return CUBEB_OK;
   1178 +  #endif
   1179 }
   1180 
   1181 int
   1182 audiounit_stream_get_current_device(cubeb_stream * stm,
   1183                                     cubeb_device ** const device)
   1184 {
   1185 #if TARGET_OS_IPHONE
   1186   // TODO
   1187 @@ -3178,16 +3250,17 @@ audiounit_stream_register_device_changed
   1188   auto_lock dev_cb_lock(stream->device_changed_callback_lock);
   1189   /* Note: second register without unregister first causes 'nope' error.
   1190    * Current implementation requires unregister before register a new cb. */
   1191   assert(!device_changed_callback || !stream->device_changed_callback);
   1192   stream->device_changed_callback = device_changed_callback;
   1193   return CUBEB_OK;
   1194 }
   1195 
   1196 +#if !TARGET_OS_IPHONE
   1197 static char *
   1198 audiounit_strref_to_cstr_utf8(CFStringRef strref)
   1199 {
   1200   CFIndex len, size;
   1201   char * ret;
   1202   if (strref == NULL) {
   1203     return NULL;
   1204   }
   1205 @@ -3199,22 +3272,24 @@ audiounit_strref_to_cstr_utf8(CFStringRe
   1206 
   1207   if (!CFStringGetCString(strref, ret, size, kCFStringEncodingUTF8)) {
   1208     delete[] ret;
   1209     ret = NULL;
   1210   }
   1211 
   1212   return ret;
   1213 }
   1214 -
   1215 +#endif
   1216 +
   1217 +#if !TARGET_OS_IPHONE
   1218 static uint32_t
   1219 audiounit_get_channel_count(AudioObjectID devid, AudioObjectPropertyScope scope)
   1220 {
   1221   AudioObjectPropertyAddress adr = {0, scope,
   1222 -                                    kAudioObjectPropertyElementMaster};
   1223 +                                    kAudioObjectPropertyElementMain};
   1224   UInt32 size = 0;
   1225   uint32_t i, ret = 0;
   1226 
   1227   adr.mSelector = kAudioDevicePropertyStreamConfiguration;
   1228 
   1229   if (AudioObjectGetPropertyDataSize(devid, &adr, 0, NULL, &size) == noErr &&
   1230       size > 0) {
   1231     AudioBufferList * list = static_cast<AudioBufferList *>(alloca(size));
   1232 @@ -3230,17 +3305,17 @@ audiounit_get_channel_count(AudioObjectI
   1233 
   1234 static void
   1235 audiounit_get_available_samplerate(AudioObjectID devid,
   1236                                    AudioObjectPropertyScope scope,
   1237                                    uint32_t * min, uint32_t * max,
   1238                                    uint32_t * def)
   1239 {
   1240   AudioObjectPropertyAddress adr = {0, scope,
   1241 -                                    kAudioObjectPropertyElementMaster};
   1242 +                                    kAudioObjectPropertyElementMain};
   1243 
   1244   adr.mSelector = kAudioDevicePropertyNominalSampleRate;
   1245   if (AudioObjectHasProperty(devid, &adr)) {
   1246     UInt32 size = sizeof(Float64);
   1247     Float64 fvalue = 0.0;
   1248     if (AudioObjectGetPropertyData(devid, &adr, 0, NULL, &size, &fvalue) ==
   1249         noErr) {
   1250       *def = fvalue;
   1251 @@ -3272,17 +3347,17 @@ audiounit_get_available_samplerate(Audio
   1252   }
   1253 }
   1254 
   1255 static UInt32
   1256 audiounit_get_device_presentation_latency(AudioObjectID devid,
   1257                                           AudioObjectPropertyScope scope)
   1258 {
   1259   AudioObjectPropertyAddress adr = {0, scope,
   1260 -                                    kAudioObjectPropertyElementMaster};
   1261 +                                    kAudioObjectPropertyElementMain};
   1262   UInt32 size, dev, stream = 0;
   1263   AudioStreamID sid[1];
   1264 
   1265   adr.mSelector = kAudioDevicePropertyLatency;
   1266   size = sizeof(UInt32);
   1267   if (AudioObjectGetPropertyData(devid, &adr, 0, NULL, &size, &dev) != noErr) {
   1268     dev = 0;
   1269   }
   1270 @@ -3297,28 +3372,32 @@ audiounit_get_device_presentation_latenc
   1271 
   1272   return dev + stream;
   1273 }
   1274 
   1275 static int
   1276 audiounit_create_device_from_hwdev(cubeb_device_info * dev_info,
   1277                                    AudioObjectID devid, cubeb_device_type type)
   1278 {
   1279 -  AudioObjectPropertyAddress adr = {0, 0, kAudioObjectPropertyElementMaster};
   1280 +  AudioObjectPropertyAddress adr = {0, 0, kAudioObjectPropertyElementMain};
   1281   UInt32 size;
   1282 
   1283   if (type == CUBEB_DEVICE_TYPE_OUTPUT) {
   1284     adr.mScope = kAudioDevicePropertyScopeOutput;
   1285   } else if (type == CUBEB_DEVICE_TYPE_INPUT) {
   1286     adr.mScope = kAudioDevicePropertyScopeInput;
   1287   } else {
   1288     return CUBEB_ERROR;
   1289   }
   1290 
   1291 +  #if TARGET_OS_IPHONE
   1292 +  UINT32 ch = 2;
   1293 +  #else
   1294   UInt32 ch = audiounit_get_channel_count(devid, adr.mScope);
   1295 +  #endif
   1296   if (ch == 0) {
   1297     return CUBEB_ERROR;
   1298   }
   1299 
   1300   PodZero(dev_info, 1);
   1301 
   1302   CFStringRef device_id_str = nullptr;
   1303   size = sizeof(CFStringRef);
   1304 @@ -3412,17 +3491,26 @@ audiounit_create_device_from_hwdev(cubeb
   1305 
   1306 bool
   1307 is_aggregate_device(cubeb_device_info * device_info)
   1308 {
   1309   assert(device_info->friendly_name);
   1310   return !strncmp(device_info->friendly_name, PRIVATE_AGGREGATE_DEVICE_NAME,
   1311                   strlen(PRIVATE_AGGREGATE_DEVICE_NAME));
   1312 }
   1313 -
   1314 +#endif
   1315 +
   1316 +#if TARGET_OS_IPHONE
   1317 +static int
   1318 +audiounit_enumerate_devices(cubeb * /* context */, cubeb_device_type type,
   1319 +                            cubeb_device_collection * collection)
   1320 +{
   1321 +  return CUBEB_ERROR_NOT_SUPPORTED;
   1322 +}
   1323 +#else
   1324 static int
   1325 audiounit_enumerate_devices(cubeb * /* context */, cubeb_device_type type,
   1326                             cubeb_device_collection * collection)
   1327 {
   1328   vector<AudioObjectID> input_devs;
   1329   vector<AudioObjectID> output_devs;
   1330 
   1331   // Count number of input and output devices.  This is not
   1332 @@ -3478,29 +3566,35 @@ audiounit_enumerate_devices(cubeb * /* c
   1333 
   1334 static void
   1335 audiounit_device_destroy(cubeb_device_info * device)
   1336 {
   1337   delete[] device->device_id;
   1338   delete[] device->friendly_name;
   1339   delete[] device->vendor_name;
   1340 }
   1341 +#endif
   1342 
   1343 static int
   1344 audiounit_device_collection_destroy(cubeb * /* context */,
   1345                                     cubeb_device_collection * collection)
   1346 {
   1347 +  #if TARGET_OS_IPHONE
   1348 +  return CUBEB_ERROR_NOT_SUPPORTED;
   1349 +  #else
   1350   for (size_t i = 0; i < collection->count; i++) {
   1351     audiounit_device_destroy(&collection->device[i]);
   1352   }
   1353   delete[] collection->device;
   1354 
   1355   return CUBEB_OK;
   1356 +  #endif
   1357 }
   1358 
   1359 +#if !TARGET_OS_IPHONE
   1360 static vector<AudioObjectID>
   1361 audiounit_get_devices_of_type(cubeb_device_type devtype)
   1362 {
   1363   UInt32 size = 0;
   1364   OSStatus ret = AudioObjectGetPropertyDataSize(
   1365       kAudioObjectSystemObject, &DEVICES_PROPERTY_ADDRESS, 0, NULL, &size);
   1366   if (ret != noErr) {
   1367     return vector<AudioObjectID>();
   1368 @@ -3653,17 +3747,28 @@ audiounit_remove_device_listener(cubeb *
   1369       context->output_collection_changed_callback) {
   1370     return noErr;
   1371   }
   1372   /* Note: unregister a non registered cb is not a problem, not checking. */
   1373   return AudioObjectRemovePropertyListener(
   1374       kAudioObjectSystemObject, &DEVICES_PROPERTY_ADDRESS,
   1375       audiounit_collection_changed_callback, context);
   1376 }
   1377 -
   1378 +#endif
   1379 +
   1380 +#if TARGET_OS_IPHONE
   1381 +int
   1382 +audiounit_register_device_collection_changed(
   1383 +    cubeb * context, cubeb_device_type devtype,
   1384 +    cubeb_device_collection_changed_callback collection_changed_callback,
   1385 +    void * user_ptr)
   1386 +{
   1387 +  return CUBEB_ERROR_NOT_SUPPORTED;
   1388 +}
   1389 +#else
   1390 int
   1391 audiounit_register_device_collection_changed(
   1392     cubeb * context, cubeb_device_type devtype,
   1393     cubeb_device_collection_changed_callback collection_changed_callback,
   1394     void * user_ptr)
   1395 {
   1396   if (devtype == CUBEB_DEVICE_TYPE_UNKNOWN) {
   1397     return CUBEB_ERROR_INVALID_PARAMETER;
   1398 @@ -3673,16 +3778,17 @@ audiounit_register_device_collection_cha
   1399   if (collection_changed_callback) {
   1400     ret = audiounit_add_device_listener(context, devtype,
   1401                                         collection_changed_callback, user_ptr);
   1402   } else {
   1403     ret = audiounit_remove_device_listener(context, devtype);
   1404   }
   1405   return (ret == noErr) ? CUBEB_OK : CUBEB_ERROR;
   1406 }
   1407 +#endif
   1408 
   1409 cubeb_ops const audiounit_ops = {
   1410     /*.init =*/audiounit_init,
   1411     /*.get_backend_id =*/audiounit_get_backend_id,
   1412     /*.get_max_channel_count =*/audiounit_get_max_channel_count,
   1413     /*.get_min_latency =*/audiounit_get_min_latency,
   1414     /*.get_preferred_sample_rate =*/audiounit_get_preferred_sample_rate,
   1415     /*.get_supported_input_processing_params =*/NULL,