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,