| 446 | } |
| 447 | |
| 448 | std::optional<int> macBluetoothNativeInputRate(const QAudioDevice& qtDevice) |
| 449 | { |
| 450 | const auto deviceId = macAudioDeviceForUid(qtDevice.id()); |
| 451 | if (!deviceId) { |
| 452 | return std::nullopt; |
| 453 | } |
| 454 | |
| 455 | const auto transport = readMacAudioScalar<UInt32>(*deviceId, kAudioDevicePropertyTransportType); |
| 456 | if (!transport |
| 457 | || (*transport != kAudioDeviceTransportTypeBluetooth |
| 458 | && *transport != kAudioDeviceTransportTypeBluetoothLE)) { |
| 459 | return std::nullopt; |
| 460 | } |
| 461 | |
| 462 | bool hasHighRate = false; |
| 463 | int exactLowRate = 0; |
| 464 | const QList<AudioValueRange> nominalRanges = readMacAudioArray<AudioValueRange>( |
| 465 | *deviceId, |
| 466 | kAudioDevicePropertyAvailableNominalSampleRates); |
| 467 | for (const AudioValueRange& range : nominalRanges) { |
| 468 | if ((range.mMinimum <= 44100.0 && range.mMaximum >= 44100.0) |
| 469 | || (range.mMinimum <= 48000.0 && range.mMaximum >= 48000.0)) { |
| 470 | hasHighRate = true; |
| 471 | } |
| 472 | |
| 473 | const int minRate = static_cast<int>(std::lround(range.mMinimum)); |
| 474 | const int maxRate = static_cast<int>(std::lround(range.mMaximum)); |
| 475 | if (minRate == maxRate && isMacBluetoothLowRate(minRate)) { |
| 476 | exactLowRate = std::max(exactLowRate, minRate); |
| 477 | } |
| 478 | } |
| 479 | |
| 480 | if (hasHighRate) { |
| 481 | return std::nullopt; |
| 482 | } |
| 483 | |
| 484 | const auto nominalRate = readMacAudioScalar<Float64>(*deviceId, kAudioDevicePropertyNominalSampleRate); |
| 485 | const int roundedNominal = nominalRate ? static_cast<int>(std::lround(*nominalRate)) : 0; |
| 486 | if (isMacBluetoothLowRate(roundedNominal)) { |
| 487 | return roundedNominal; |
| 488 | } |
| 489 | |
| 490 | if (exactLowRate > 0) { |
| 491 | return exactLowRate; |
| 492 | } |
| 493 | |
| 494 | return std::nullopt; |
| 495 | } |
| 496 | // (macTxInputRateCandidates removed — TX mic rate negotiation now goes through |
| 497 | // the consolidated AudioFormatNegotiator ladder; #2930's preferred-rate-first |
| 498 | // and #2615's Bluetooth-HFP native rate are encoded there, fed by |
no test coverage detected