audio_device_pulse_linux.cc (62809B)
1 /* 2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11 #include "modules/audio_device/linux/audio_device_pulse_linux.h" 12 13 #include <cstddef> 14 #include <cstdint> 15 #include <cstring> 16 17 #include "api/audio/audio_device.h" 18 #include "api/audio/audio_device_defines.h" 19 #include "api/units/time_delta.h" 20 #include "modules/audio_device/audio_device_buffer.h" 21 #include "modules/audio_device/audio_device_generic.h" 22 #include "modules/audio_device/linux/latebindingsymboltable_linux.h" 23 #include "rtc_base/checks.h" 24 #include "rtc_base/logging.h" 25 #include "rtc_base/platform_thread.h" 26 #include "rtc_base/synchronization/mutex.h" 27 #include "rtc_base/thread_annotations.h" 28 29 #if defined(WEBRTC_USE_X11) 30 #include <X11/Xlib.h> 31 #endif 32 33 WebRTCPulseSymbolTable* GetPulseSymbolTable() { 34 static WebRTCPulseSymbolTable* pulse_symbol_table = 35 new WebRTCPulseSymbolTable(); 36 return pulse_symbol_table; 37 } 38 39 // Accesses Pulse functions through our late-binding symbol table instead of 40 // directly. This way we don't have to link to libpulse, which means our binary 41 // will work on systems that don't have it. 42 #define LATE(sym) \ 43 LATESYM_GET(webrtc::adm_linux_pulse::PulseAudioSymbolTable, \ 44 GetPulseSymbolTable(), sym) 45 46 namespace webrtc { 47 48 AudioDeviceLinuxPulse::AudioDeviceLinuxPulse() 49 : _ptrAudioBuffer(nullptr), 50 _inputDeviceIndex(0), 51 _outputDeviceIndex(0), 52 _inputDeviceIsSpecified(false), 53 _outputDeviceIsSpecified(false), 54 sample_rate_hz_(0), 55 _recChannels(1), 56 _playChannels(1), 57 _initialized(false), 58 _recording(false), 59 _playing(false), 60 _recIsInitialized(false), 61 _playIsInitialized(false), 62 _startRec(false), 63 _startPlay(false), 64 update_speaker_volume_at_startup_(false), 65 quit_(false), 66 _sndCardPlayDelay(0), 67 _writeErrors(0), 68 _deviceIndex(-1), 69 _numPlayDevices(0), 70 _numRecDevices(0), 71 _playDeviceName(nullptr), 72 _recDeviceName(nullptr), 73 _playDisplayDeviceName(nullptr), 74 _recDisplayDeviceName(nullptr), 75 _playBuffer(nullptr), 76 _playbackBufferSize(0), 77 _playbackBufferUnused(0), 78 _tempBufferSpace(0), 79 _recBuffer(nullptr), 80 _recordBufferSize(0), 81 _recordBufferUsed(0), 82 _tempSampleData(nullptr), 83 _tempSampleDataSize(0), 84 _configuredLatencyPlay(0), 85 _configuredLatencyRec(0), 86 _paDeviceIndex(-1), 87 _paStateChanged(false), 88 _paMainloop(nullptr), 89 _paMainloopApi(nullptr), 90 _paContext(nullptr), 91 _recStream(nullptr), 92 _playStream(nullptr), 93 _recStreamFlags(0), 94 _playStreamFlags(0) { 95 RTC_DLOG(LS_INFO) << __FUNCTION__ << " created"; 96 97 memset(_paServerVersion, 0, sizeof(_paServerVersion)); 98 memset(&_playBufferAttr, 0, sizeof(_playBufferAttr)); 99 memset(&_recBufferAttr, 0, sizeof(_recBufferAttr)); 100 memset(_oldKeyState, 0, sizeof(_oldKeyState)); 101 } 102 103 AudioDeviceLinuxPulse::~AudioDeviceLinuxPulse() { 104 RTC_DLOG(LS_INFO) << __FUNCTION__ << " destroyed"; 105 RTC_DCHECK(thread_checker_.IsCurrent()); 106 Terminate(); 107 108 if (_recBuffer) { 109 delete[] _recBuffer; 110 _recBuffer = nullptr; 111 } 112 if (_playBuffer) { 113 delete[] _playBuffer; 114 _playBuffer = nullptr; 115 } 116 if (_playDeviceName) { 117 delete[] _playDeviceName; 118 _playDeviceName = nullptr; 119 } 120 if (_recDeviceName) { 121 delete[] _recDeviceName; 122 _recDeviceName = nullptr; 123 } 124 } 125 126 void AudioDeviceLinuxPulse::AttachAudioBuffer(AudioDeviceBuffer* audioBuffer) { 127 RTC_DCHECK(thread_checker_.IsCurrent()); 128 129 _ptrAudioBuffer = audioBuffer; 130 131 // Inform the AudioBuffer about default settings for this implementation. 132 // Set all values to zero here since the actual settings will be done by 133 // InitPlayout and InitRecording later. 134 _ptrAudioBuffer->SetRecordingSampleRate(0); 135 _ptrAudioBuffer->SetPlayoutSampleRate(0); 136 _ptrAudioBuffer->SetRecordingChannels(0); 137 _ptrAudioBuffer->SetPlayoutChannels(0); 138 } 139 140 // ---------------------------------------------------------------------------- 141 // ActiveAudioLayer 142 // ---------------------------------------------------------------------------- 143 144 int32_t AudioDeviceLinuxPulse::ActiveAudioLayer( 145 AudioDeviceModule::AudioLayer& audioLayer) const { 146 audioLayer = AudioDeviceModule::kLinuxPulseAudio; 147 return 0; 148 } 149 150 AudioDeviceGeneric::InitStatus AudioDeviceLinuxPulse::Init() { 151 RTC_DCHECK(thread_checker_.IsCurrent()); 152 if (_initialized) { 153 return InitStatus::OK; 154 } 155 156 // Initialize PulseAudio 157 if (InitPulseAudio() < 0) { 158 RTC_LOG(LS_ERROR) << "failed to initialize PulseAudio"; 159 if (TerminatePulseAudio() < 0) { 160 RTC_LOG(LS_ERROR) << "failed to terminate PulseAudio"; 161 } 162 return InitStatus::OTHER_ERROR; 163 } 164 165 #if defined(WEBRTC_USE_X11) 166 // Get X display handle for typing detection 167 _XDisplay = XOpenDisplay(nullptr); 168 if (!_XDisplay) { 169 RTC_LOG(LS_WARNING) 170 << "failed to open X display, typing detection will not work"; 171 } 172 #endif 173 174 // RECORDING 175 const auto attributes = 176 ThreadAttributes().SetPriority(ThreadPriority::kRealtime); 177 _ptrThreadRec = PlatformThread::SpawnJoinable( 178 [this] { 179 while (RecThreadProcess()) { 180 } 181 }, 182 "webrtc_audio_module_rec_thread", attributes); 183 184 // PLAYOUT 185 _ptrThreadPlay = PlatformThread::SpawnJoinable( 186 [this] { 187 while (PlayThreadProcess()) { 188 } 189 }, 190 "webrtc_audio_module_play_thread", attributes); 191 _initialized = true; 192 193 return InitStatus::OK; 194 } 195 196 int32_t AudioDeviceLinuxPulse::Terminate() { 197 RTC_DCHECK(thread_checker_.IsCurrent()); 198 if (!_initialized) { 199 return 0; 200 } 201 { 202 MutexLock lock(&mutex_); 203 quit_ = true; 204 } 205 _mixerManager.Close(); 206 207 // RECORDING 208 _timeEventRec.Set(); 209 _ptrThreadRec.Finalize(); 210 211 // PLAYOUT 212 _timeEventPlay.Set(); 213 _ptrThreadPlay.Finalize(); 214 215 // Terminate PulseAudio 216 if (TerminatePulseAudio() < 0) { 217 RTC_LOG(LS_ERROR) << "failed to terminate PulseAudio"; 218 return -1; 219 } 220 221 #if defined(WEBRTC_USE_X11) 222 if (_XDisplay) { 223 XCloseDisplay(_XDisplay); 224 _XDisplay = nullptr; 225 } 226 #endif 227 228 _initialized = false; 229 _outputDeviceIsSpecified = false; 230 _inputDeviceIsSpecified = false; 231 232 return 0; 233 } 234 235 bool AudioDeviceLinuxPulse::Initialized() const { 236 RTC_DCHECK(thread_checker_.IsCurrent()); 237 return (_initialized); 238 } 239 240 int32_t AudioDeviceLinuxPulse::InitSpeaker() { 241 RTC_DCHECK(thread_checker_.IsCurrent()); 242 243 if (_playing) { 244 return -1; 245 } 246 247 if (!_outputDeviceIsSpecified) { 248 return -1; 249 } 250 251 // check if default device 252 if (_outputDeviceIndex == 0) { 253 uint16_t deviceIndex = 0; 254 GetDefaultDeviceInfo(false, nullptr, deviceIndex); 255 _paDeviceIndex = deviceIndex; 256 } else { 257 // get the PA device index from 258 // the callback 259 _deviceIndex = _outputDeviceIndex; 260 261 // get playout devices 262 PlayoutDevices(); 263 } 264 265 // the callback has now set the _paDeviceIndex to 266 // the PulseAudio index of the device 267 if (_mixerManager.OpenSpeaker(_paDeviceIndex) == -1) { 268 return -1; 269 } 270 271 // clear _deviceIndex 272 _deviceIndex = -1; 273 _paDeviceIndex = -1; 274 275 return 0; 276 } 277 278 int32_t AudioDeviceLinuxPulse::InitMicrophone() { 279 RTC_DCHECK(thread_checker_.IsCurrent()); 280 if (_recording) { 281 return -1; 282 } 283 284 if (!_inputDeviceIsSpecified) { 285 return -1; 286 } 287 288 // Check if default device 289 if (_inputDeviceIndex == 0) { 290 uint16_t deviceIndex = 0; 291 GetDefaultDeviceInfo(true, nullptr, deviceIndex); 292 _paDeviceIndex = deviceIndex; 293 } else { 294 // Get the PA device index from 295 // the callback 296 _deviceIndex = _inputDeviceIndex; 297 298 // get recording devices 299 RecordingDevices(); 300 } 301 302 // The callback has now set the _paDeviceIndex to 303 // the PulseAudio index of the device 304 if (_mixerManager.OpenMicrophone(_paDeviceIndex) == -1) { 305 return -1; 306 } 307 308 // Clear _deviceIndex 309 _deviceIndex = -1; 310 _paDeviceIndex = -1; 311 312 return 0; 313 } 314 315 bool AudioDeviceLinuxPulse::SpeakerIsInitialized() const { 316 RTC_DCHECK(thread_checker_.IsCurrent()); 317 return (_mixerManager.SpeakerIsInitialized()); 318 } 319 320 bool AudioDeviceLinuxPulse::MicrophoneIsInitialized() const { 321 RTC_DCHECK(thread_checker_.IsCurrent()); 322 return (_mixerManager.MicrophoneIsInitialized()); 323 } 324 325 int32_t AudioDeviceLinuxPulse::SpeakerVolumeIsAvailable(bool& available) { 326 RTC_DCHECK(thread_checker_.IsCurrent()); 327 bool wasInitialized = _mixerManager.SpeakerIsInitialized(); 328 329 // Make an attempt to open up the 330 // output mixer corresponding to the currently selected output device. 331 if (!wasInitialized && InitSpeaker() == -1) { 332 // If we end up here it means that the selected speaker has no volume 333 // control. 334 available = false; 335 return 0; 336 } 337 338 // Given that InitSpeaker was successful, we know volume control exists. 339 available = true; 340 341 // Close the initialized output mixer 342 if (!wasInitialized) { 343 _mixerManager.CloseSpeaker(); 344 } 345 346 return 0; 347 } 348 349 int32_t AudioDeviceLinuxPulse::SetSpeakerVolume(uint32_t volume) { 350 RTC_DCHECK(thread_checker_.IsCurrent()); 351 if (!_playing) { 352 // Only update the volume if it's been set while we weren't playing. 353 update_speaker_volume_at_startup_ = true; 354 } 355 return (_mixerManager.SetSpeakerVolume(volume)); 356 } 357 358 int32_t AudioDeviceLinuxPulse::SpeakerVolume(uint32_t& volume) const { 359 RTC_DCHECK(thread_checker_.IsCurrent()); 360 uint32_t level(0); 361 362 if (_mixerManager.SpeakerVolume(level) == -1) { 363 return -1; 364 } 365 366 volume = level; 367 368 return 0; 369 } 370 371 int32_t AudioDeviceLinuxPulse::MaxSpeakerVolume(uint32_t& maxVolume) const { 372 RTC_DCHECK(thread_checker_.IsCurrent()); 373 uint32_t maxVol(0); 374 375 if (_mixerManager.MaxSpeakerVolume(maxVol) == -1) { 376 return -1; 377 } 378 379 maxVolume = maxVol; 380 381 return 0; 382 } 383 384 int32_t AudioDeviceLinuxPulse::MinSpeakerVolume(uint32_t& minVolume) const { 385 RTC_DCHECK(thread_checker_.IsCurrent()); 386 uint32_t minVol(0); 387 388 if (_mixerManager.MinSpeakerVolume(minVol) == -1) { 389 return -1; 390 } 391 392 minVolume = minVol; 393 394 return 0; 395 } 396 397 int32_t AudioDeviceLinuxPulse::SpeakerMuteIsAvailable(bool& available) { 398 RTC_DCHECK(thread_checker_.IsCurrent()); 399 bool isAvailable(false); 400 bool wasInitialized = _mixerManager.SpeakerIsInitialized(); 401 402 // Make an attempt to open up the 403 // output mixer corresponding to the currently selected output device. 404 // 405 if (!wasInitialized && InitSpeaker() == -1) { 406 // If we end up here it means that the selected speaker has no volume 407 // control, hence it is safe to state that there is no mute control 408 // already at this stage. 409 available = false; 410 return 0; 411 } 412 413 // Check if the selected speaker has a mute control 414 _mixerManager.SpeakerMuteIsAvailable(isAvailable); 415 416 available = isAvailable; 417 418 // Close the initialized output mixer 419 if (!wasInitialized) { 420 _mixerManager.CloseSpeaker(); 421 } 422 423 return 0; 424 } 425 426 int32_t AudioDeviceLinuxPulse::SetSpeakerMute(bool enable) { 427 RTC_DCHECK(thread_checker_.IsCurrent()); 428 return (_mixerManager.SetSpeakerMute(enable)); 429 } 430 431 int32_t AudioDeviceLinuxPulse::SpeakerMute(bool& enabled) const { 432 RTC_DCHECK(thread_checker_.IsCurrent()); 433 bool muted(0); 434 if (_mixerManager.SpeakerMute(muted) == -1) { 435 return -1; 436 } 437 438 enabled = muted; 439 return 0; 440 } 441 442 int32_t AudioDeviceLinuxPulse::MicrophoneMuteIsAvailable(bool& available) { 443 RTC_DCHECK(thread_checker_.IsCurrent()); 444 bool isAvailable(false); 445 bool wasInitialized = _mixerManager.MicrophoneIsInitialized(); 446 447 // Make an attempt to open up the 448 // input mixer corresponding to the currently selected input device. 449 // 450 if (!wasInitialized && InitMicrophone() == -1) { 451 // If we end up here it means that the selected microphone has no 452 // volume control, hence it is safe to state that there is no 453 // boost control already at this stage. 454 available = false; 455 return 0; 456 } 457 458 // Check if the selected microphone has a mute control 459 // 460 _mixerManager.MicrophoneMuteIsAvailable(isAvailable); 461 available = isAvailable; 462 463 // Close the initialized input mixer 464 // 465 if (!wasInitialized) { 466 _mixerManager.CloseMicrophone(); 467 } 468 469 return 0; 470 } 471 472 int32_t AudioDeviceLinuxPulse::SetMicrophoneMute(bool enable) { 473 RTC_DCHECK(thread_checker_.IsCurrent()); 474 return (_mixerManager.SetMicrophoneMute(enable)); 475 } 476 477 int32_t AudioDeviceLinuxPulse::MicrophoneMute(bool& enabled) const { 478 RTC_DCHECK(thread_checker_.IsCurrent()); 479 bool muted(0); 480 if (_mixerManager.MicrophoneMute(muted) == -1) { 481 return -1; 482 } 483 484 enabled = muted; 485 return 0; 486 } 487 488 int32_t AudioDeviceLinuxPulse::StereoRecordingIsAvailable(bool& available) { 489 RTC_DCHECK(thread_checker_.IsCurrent()); 490 if (_recChannels == 2 && _recording) { 491 available = true; 492 return 0; 493 } 494 495 available = false; 496 bool wasInitialized = _mixerManager.MicrophoneIsInitialized(); 497 int error = 0; 498 499 if (!wasInitialized && InitMicrophone() == -1) { 500 // Cannot open the specified device 501 available = false; 502 return 0; 503 } 504 505 // Check if the selected microphone can record stereo. 506 bool isAvailable(false); 507 error = _mixerManager.StereoRecordingIsAvailable(isAvailable); 508 if (!error) 509 available = isAvailable; 510 511 // Close the initialized input mixer 512 if (!wasInitialized) { 513 _mixerManager.CloseMicrophone(); 514 } 515 516 return error; 517 } 518 519 int32_t AudioDeviceLinuxPulse::SetStereoRecording(bool enable) { 520 RTC_DCHECK(thread_checker_.IsCurrent()); 521 if (enable) 522 _recChannels = 2; 523 else 524 _recChannels = 1; 525 526 return 0; 527 } 528 529 int32_t AudioDeviceLinuxPulse::StereoRecording(bool& enabled) const { 530 RTC_DCHECK(thread_checker_.IsCurrent()); 531 if (_recChannels == 2) 532 enabled = true; 533 else 534 enabled = false; 535 536 return 0; 537 } 538 539 int32_t AudioDeviceLinuxPulse::StereoPlayoutIsAvailable(bool& available) { 540 RTC_DCHECK(thread_checker_.IsCurrent()); 541 if (_playChannels == 2 && _playing) { 542 available = true; 543 return 0; 544 } 545 546 available = false; 547 bool wasInitialized = _mixerManager.SpeakerIsInitialized(); 548 int error = 0; 549 550 if (!wasInitialized && InitSpeaker() == -1) { 551 // Cannot open the specified device. 552 return -1; 553 } 554 555 // Check if the selected speaker can play stereo. 556 bool isAvailable(false); 557 error = _mixerManager.StereoPlayoutIsAvailable(isAvailable); 558 if (!error) 559 available = isAvailable; 560 561 // Close the initialized input mixer 562 if (!wasInitialized) { 563 _mixerManager.CloseSpeaker(); 564 } 565 566 return error; 567 } 568 569 int32_t AudioDeviceLinuxPulse::SetStereoPlayout(bool enable) { 570 RTC_DCHECK(thread_checker_.IsCurrent()); 571 if (enable) 572 _playChannels = 2; 573 else 574 _playChannels = 1; 575 576 return 0; 577 } 578 579 int32_t AudioDeviceLinuxPulse::StereoPlayout(bool& enabled) const { 580 RTC_DCHECK(thread_checker_.IsCurrent()); 581 if (_playChannels == 2) 582 enabled = true; 583 else 584 enabled = false; 585 586 return 0; 587 } 588 589 int32_t AudioDeviceLinuxPulse::MicrophoneVolumeIsAvailable(bool& available) { 590 RTC_DCHECK(thread_checker_.IsCurrent()); 591 bool wasInitialized = _mixerManager.MicrophoneIsInitialized(); 592 593 // Make an attempt to open up the 594 // input mixer corresponding to the currently selected output device. 595 if (!wasInitialized && InitMicrophone() == -1) { 596 // If we end up here it means that the selected microphone has no 597 // volume control. 598 available = false; 599 return 0; 600 } 601 602 // Given that InitMicrophone was successful, we know that a volume control 603 // exists. 604 available = true; 605 606 // Close the initialized input mixer 607 if (!wasInitialized) { 608 _mixerManager.CloseMicrophone(); 609 } 610 611 return 0; 612 } 613 614 int32_t AudioDeviceLinuxPulse::SetMicrophoneVolume(uint32_t volume) { 615 return (_mixerManager.SetMicrophoneVolume(volume)); 616 } 617 618 int32_t AudioDeviceLinuxPulse::MicrophoneVolume(uint32_t& volume) const { 619 uint32_t level(0); 620 621 if (_mixerManager.MicrophoneVolume(level) == -1) { 622 RTC_LOG(LS_WARNING) << "failed to retrieve current microphone level"; 623 return -1; 624 } 625 626 volume = level; 627 628 return 0; 629 } 630 631 int32_t AudioDeviceLinuxPulse::MaxMicrophoneVolume(uint32_t& maxVolume) const { 632 uint32_t maxVol(0); 633 634 if (_mixerManager.MaxMicrophoneVolume(maxVol) == -1) { 635 return -1; 636 } 637 638 maxVolume = maxVol; 639 640 return 0; 641 } 642 643 int32_t AudioDeviceLinuxPulse::MinMicrophoneVolume(uint32_t& minVolume) const { 644 uint32_t minVol(0); 645 646 if (_mixerManager.MinMicrophoneVolume(minVol) == -1) { 647 return -1; 648 } 649 650 minVolume = minVol; 651 652 return 0; 653 } 654 655 int16_t AudioDeviceLinuxPulse::PlayoutDevices() { 656 PaLock(); 657 658 pa_operation* paOperation = nullptr; 659 _numPlayDevices = 1; // init to 1 to account for "default" 660 661 // get the whole list of devices and update _numPlayDevices 662 paOperation = 663 LATE(pa_context_get_sink_info_list)(_paContext, PaSinkInfoCallback, this); 664 665 WaitForOperationCompletion(paOperation); 666 667 PaUnLock(); 668 669 return _numPlayDevices; 670 } 671 672 int32_t AudioDeviceLinuxPulse::SetPlayoutDevice(uint16_t index) { 673 RTC_DCHECK(thread_checker_.IsCurrent()); 674 if (_playIsInitialized) { 675 return -1; 676 } 677 678 const uint16_t nDevices = PlayoutDevices(); 679 680 RTC_LOG(LS_VERBOSE) << "number of availiable output devices is " << nDevices; 681 682 if (index > (nDevices - 1)) { 683 RTC_LOG(LS_ERROR) << "device index is out of range [0," << (nDevices - 1) 684 << "]"; 685 return -1; 686 } 687 688 _outputDeviceIndex = index; 689 _outputDeviceIsSpecified = true; 690 691 return 0; 692 } 693 694 int32_t AudioDeviceLinuxPulse::SetPlayoutDevice( 695 AudioDeviceModule::WindowsDeviceType /*device*/) { 696 RTC_LOG(LS_ERROR) << "WindowsDeviceType not supported"; 697 return -1; 698 } 699 700 int32_t AudioDeviceLinuxPulse::PlayoutDeviceName( 701 uint16_t index, 702 char name[kAdmMaxDeviceNameSize], 703 char guid[kAdmMaxGuidSize]) { 704 RTC_DCHECK(thread_checker_.IsCurrent()); 705 const uint16_t nDevices = PlayoutDevices(); 706 707 if ((index > (nDevices - 1)) || (name == nullptr)) { 708 return -1; 709 } 710 711 memset(name, 0, kAdmMaxDeviceNameSize); 712 713 if (guid != nullptr) { 714 memset(guid, 0, kAdmMaxGuidSize); 715 } 716 717 // Check if default device 718 if (index == 0) { 719 uint16_t deviceIndex = 0; 720 return GetDefaultDeviceInfo(false, name, deviceIndex); 721 } 722 723 // Tell the callback that we want 724 // The name for this device 725 _playDisplayDeviceName = name; 726 _deviceIndex = index; 727 728 // get playout devices 729 PlayoutDevices(); 730 731 // clear device name and index 732 _playDisplayDeviceName = nullptr; 733 _deviceIndex = -1; 734 735 return 0; 736 } 737 738 int32_t AudioDeviceLinuxPulse::RecordingDeviceName( 739 uint16_t index, 740 char name[kAdmMaxDeviceNameSize], 741 char guid[kAdmMaxGuidSize]) { 742 RTC_DCHECK(thread_checker_.IsCurrent()); 743 const uint16_t nDevices(RecordingDevices()); 744 745 if ((index > (nDevices - 1)) || (name == nullptr)) { 746 return -1; 747 } 748 749 memset(name, 0, kAdmMaxDeviceNameSize); 750 751 if (guid != nullptr) { 752 memset(guid, 0, kAdmMaxGuidSize); 753 } 754 755 // Check if default device 756 if (index == 0) { 757 uint16_t deviceIndex = 0; 758 return GetDefaultDeviceInfo(true, name, deviceIndex); 759 } 760 761 // Tell the callback that we want 762 // the name for this device 763 _recDisplayDeviceName = name; 764 _deviceIndex = index; 765 766 // Get recording devices 767 RecordingDevices(); 768 769 // Clear device name and index 770 _recDisplayDeviceName = nullptr; 771 _deviceIndex = -1; 772 773 return 0; 774 } 775 776 int16_t AudioDeviceLinuxPulse::RecordingDevices() { 777 PaLock(); 778 779 pa_operation* paOperation = nullptr; 780 _numRecDevices = 1; // Init to 1 to account for "default" 781 782 // Get the whole list of devices and update _numRecDevices 783 paOperation = LATE(pa_context_get_source_info_list)( 784 _paContext, PaSourceInfoCallback, this); 785 786 WaitForOperationCompletion(paOperation); 787 788 PaUnLock(); 789 790 return _numRecDevices; 791 } 792 793 int32_t AudioDeviceLinuxPulse::SetRecordingDevice(uint16_t index) { 794 RTC_DCHECK(thread_checker_.IsCurrent()); 795 if (_recIsInitialized) { 796 return -1; 797 } 798 799 const uint16_t nDevices(RecordingDevices()); 800 801 RTC_LOG(LS_VERBOSE) << "number of availiable input devices is " << nDevices; 802 803 if (index > (nDevices - 1)) { 804 RTC_LOG(LS_ERROR) << "device index is out of range [0," << (nDevices - 1) 805 << "]"; 806 return -1; 807 } 808 809 _inputDeviceIndex = index; 810 _inputDeviceIsSpecified = true; 811 812 return 0; 813 } 814 815 int32_t AudioDeviceLinuxPulse::SetRecordingDevice( 816 AudioDeviceModule::WindowsDeviceType /*device*/) { 817 RTC_LOG(LS_ERROR) << "WindowsDeviceType not supported"; 818 return -1; 819 } 820 821 int32_t AudioDeviceLinuxPulse::PlayoutIsAvailable(bool& available) { 822 RTC_DCHECK(thread_checker_.IsCurrent()); 823 available = false; 824 825 // Try to initialize the playout side 826 int32_t res = InitPlayout(); 827 828 // Cancel effect of initialization 829 StopPlayout(); 830 831 if (res != -1) { 832 available = true; 833 } 834 835 return res; 836 } 837 838 int32_t AudioDeviceLinuxPulse::RecordingIsAvailable(bool& available) { 839 RTC_DCHECK(thread_checker_.IsCurrent()); 840 available = false; 841 842 // Try to initialize the playout side 843 int32_t res = InitRecording(); 844 845 // Cancel effect of initialization 846 StopRecording(); 847 848 if (res != -1) { 849 available = true; 850 } 851 852 return res; 853 } 854 855 int32_t AudioDeviceLinuxPulse::InitPlayout() { 856 RTC_DCHECK(thread_checker_.IsCurrent()); 857 858 if (_playing) { 859 return -1; 860 } 861 862 if (!_outputDeviceIsSpecified) { 863 return -1; 864 } 865 866 if (_playIsInitialized) { 867 return 0; 868 } 869 870 // Initialize the speaker (devices might have been added or removed) 871 if (InitSpeaker() == -1) { 872 RTC_LOG(LS_WARNING) << "InitSpeaker() failed"; 873 } 874 875 // Set the play sample specification 876 pa_sample_spec playSampleSpec; 877 playSampleSpec.channels = _playChannels; 878 playSampleSpec.format = PA_SAMPLE_S16LE; 879 playSampleSpec.rate = sample_rate_hz_; 880 881 // Create a new play stream 882 { 883 MutexLock lock(&mutex_); 884 _playStream = 885 LATE(pa_stream_new)(_paContext, "playStream", &playSampleSpec, nullptr); 886 } 887 888 if (!_playStream) { 889 RTC_LOG(LS_ERROR) << "failed to create play stream, err=" 890 << LATE(pa_context_errno)(_paContext); 891 return -1; 892 } 893 894 // Provide the playStream to the mixer 895 _mixerManager.SetPlayStream(_playStream); 896 897 if (_ptrAudioBuffer) { 898 // Update audio buffer with the selected parameters 899 _ptrAudioBuffer->SetPlayoutSampleRate(sample_rate_hz_); 900 _ptrAudioBuffer->SetPlayoutChannels((uint8_t)_playChannels); 901 } 902 903 RTC_LOG(LS_VERBOSE) << "stream state " 904 << LATE(pa_stream_get_state)(_playStream); 905 906 // Set stream flags 907 _playStreamFlags = (pa_stream_flags_t)(PA_STREAM_AUTO_TIMING_UPDATE | 908 PA_STREAM_INTERPOLATE_TIMING); 909 910 if (_configuredLatencyPlay != WEBRTC_PA_NO_LATENCY_REQUIREMENTS) { 911 // If configuring a specific latency then we want to specify 912 // PA_STREAM_ADJUST_LATENCY to make the server adjust parameters 913 // automatically to reach that target latency. However, that flag 914 // doesn't exist in Ubuntu 8.04 and many people still use that, 915 // so we have to check the protocol version of libpulse. 916 if (LATE(pa_context_get_protocol_version)(_paContext) >= 917 WEBRTC_PA_ADJUST_LATENCY_PROTOCOL_VERSION) { 918 _playStreamFlags |= PA_STREAM_ADJUST_LATENCY; 919 } 920 921 const pa_sample_spec* spec = LATE(pa_stream_get_sample_spec)(_playStream); 922 if (!spec) { 923 RTC_LOG(LS_ERROR) << "pa_stream_get_sample_spec()"; 924 return -1; 925 } 926 927 size_t bytesPerSec = LATE(pa_bytes_per_second)(spec); 928 uint32_t latency = bytesPerSec * WEBRTC_PA_PLAYBACK_LATENCY_MINIMUM_MSECS / 929 WEBRTC_PA_MSECS_PER_SEC; 930 931 // Set the play buffer attributes 932 _playBufferAttr.maxlength = latency; // num bytes stored in the buffer 933 _playBufferAttr.tlength = latency; // target fill level of play buffer 934 // minimum free num bytes before server request more data 935 _playBufferAttr.minreq = latency / WEBRTC_PA_PLAYBACK_REQUEST_FACTOR; 936 // prebuffer tlength before starting playout 937 _playBufferAttr.prebuf = _playBufferAttr.tlength - _playBufferAttr.minreq; 938 939 _configuredLatencyPlay = latency; 940 } 941 942 // num samples in bytes * num channels 943 _playbackBufferSize = sample_rate_hz_ / 100 * 2 * _playChannels; 944 _playbackBufferUnused = _playbackBufferSize; 945 _playBuffer = new int8_t[_playbackBufferSize]; 946 947 // Enable underflow callback 948 LATE(pa_stream_set_underflow_callback) 949 (_playStream, PaStreamUnderflowCallback, this); 950 951 // Set the state callback function for the stream 952 LATE(pa_stream_set_state_callback)(_playStream, PaStreamStateCallback, this); 953 954 // Mark playout side as initialized 955 { 956 MutexLock lock(&mutex_); 957 _playIsInitialized = true; 958 _sndCardPlayDelay = 0; 959 } 960 961 return 0; 962 } 963 964 int32_t AudioDeviceLinuxPulse::InitRecording() { 965 RTC_DCHECK(thread_checker_.IsCurrent()); 966 967 if (_recording) { 968 return -1; 969 } 970 971 if (!_inputDeviceIsSpecified) { 972 return -1; 973 } 974 975 if (_recIsInitialized) { 976 return 0; 977 } 978 979 // Initialize the microphone (devices might have been added or removed) 980 if (InitMicrophone() == -1) { 981 RTC_LOG(LS_WARNING) << "InitMicrophone() failed"; 982 } 983 984 // Set the rec sample specification 985 pa_sample_spec recSampleSpec; 986 recSampleSpec.channels = _recChannels; 987 recSampleSpec.format = PA_SAMPLE_S16LE; 988 recSampleSpec.rate = sample_rate_hz_; 989 990 // Create a new rec stream 991 _recStream = 992 LATE(pa_stream_new)(_paContext, "recStream", &recSampleSpec, nullptr); 993 if (!_recStream) { 994 RTC_LOG(LS_ERROR) << "failed to create rec stream, err=" 995 << LATE(pa_context_errno)(_paContext); 996 return -1; 997 } 998 999 // Provide the recStream to the mixer 1000 _mixerManager.SetRecStream(_recStream); 1001 1002 if (_ptrAudioBuffer) { 1003 // Update audio buffer with the selected parameters 1004 _ptrAudioBuffer->SetRecordingSampleRate(sample_rate_hz_); 1005 _ptrAudioBuffer->SetRecordingChannels((uint8_t)_recChannels); 1006 } 1007 1008 if (_configuredLatencyRec != WEBRTC_PA_NO_LATENCY_REQUIREMENTS) { 1009 _recStreamFlags = (pa_stream_flags_t)(PA_STREAM_AUTO_TIMING_UPDATE | 1010 PA_STREAM_INTERPOLATE_TIMING); 1011 1012 // If configuring a specific latency then we want to specify 1013 // PA_STREAM_ADJUST_LATENCY to make the server adjust parameters 1014 // automatically to reach that target latency. However, that flag 1015 // doesn't exist in Ubuntu 8.04 and many people still use that, 1016 // so we have to check the protocol version of libpulse. 1017 if (LATE(pa_context_get_protocol_version)(_paContext) >= 1018 WEBRTC_PA_ADJUST_LATENCY_PROTOCOL_VERSION) { 1019 _recStreamFlags |= PA_STREAM_ADJUST_LATENCY; 1020 } 1021 1022 const pa_sample_spec* spec = LATE(pa_stream_get_sample_spec)(_recStream); 1023 if (!spec) { 1024 RTC_LOG(LS_ERROR) << "pa_stream_get_sample_spec(rec)"; 1025 return -1; 1026 } 1027 1028 size_t bytesPerSec = LATE(pa_bytes_per_second)(spec); 1029 uint32_t latency = bytesPerSec * WEBRTC_PA_LOW_CAPTURE_LATENCY_MSECS / 1030 WEBRTC_PA_MSECS_PER_SEC; 1031 1032 // Set the rec buffer attributes 1033 // Note: fragsize specifies a maximum transfer size, not a minimum, so 1034 // it is not possible to force a high latency setting, only a low one. 1035 _recBufferAttr.fragsize = latency; // size of fragment 1036 _recBufferAttr.maxlength = 1037 latency + bytesPerSec * WEBRTC_PA_CAPTURE_BUFFER_EXTRA_MSECS / 1038 WEBRTC_PA_MSECS_PER_SEC; 1039 1040 _configuredLatencyRec = latency; 1041 } 1042 1043 _recordBufferSize = sample_rate_hz_ / 100 * 2 * _recChannels; 1044 _recordBufferUsed = 0; 1045 _recBuffer = new int8_t[_recordBufferSize]; 1046 1047 // Enable overflow callback 1048 LATE(pa_stream_set_overflow_callback) 1049 (_recStream, PaStreamOverflowCallback, this); 1050 1051 // Set the state callback function for the stream 1052 LATE(pa_stream_set_state_callback)(_recStream, PaStreamStateCallback, this); 1053 1054 // Mark recording side as initialized 1055 _recIsInitialized = true; 1056 1057 return 0; 1058 } 1059 1060 int32_t AudioDeviceLinuxPulse::StartRecording() { 1061 RTC_DCHECK(thread_checker_.IsCurrent()); 1062 if (!_recIsInitialized) { 1063 return -1; 1064 } 1065 1066 if (_recording) { 1067 return 0; 1068 } 1069 1070 // Set state to ensure that the recording starts from the audio thread. 1071 _startRec = true; 1072 1073 // The audio thread will signal when recording has started. 1074 _timeEventRec.Set(); 1075 if (!_recStartEvent.Wait(TimeDelta::Seconds(10))) { 1076 { 1077 MutexLock lock(&mutex_); 1078 _startRec = false; 1079 } 1080 StopRecording(); 1081 RTC_LOG(LS_ERROR) << "failed to activate recording"; 1082 return -1; 1083 } 1084 1085 { 1086 MutexLock lock(&mutex_); 1087 if (_recording) { 1088 // The recording state is set by the audio thread after recording 1089 // has started. 1090 } else { 1091 RTC_LOG(LS_ERROR) << "failed to activate recording"; 1092 return -1; 1093 } 1094 } 1095 1096 return 0; 1097 } 1098 1099 int32_t AudioDeviceLinuxPulse::StopRecording() { 1100 RTC_DCHECK(thread_checker_.IsCurrent()); 1101 MutexLock lock(&mutex_); 1102 1103 if (!_recIsInitialized) { 1104 return 0; 1105 } 1106 1107 if (_recStream == nullptr) { 1108 return -1; 1109 } 1110 1111 _recIsInitialized = false; 1112 _recording = false; 1113 1114 RTC_LOG(LS_VERBOSE) << "stopping recording"; 1115 1116 // Stop Recording 1117 PaLock(); 1118 1119 DisableReadCallback(); 1120 LATE(pa_stream_set_overflow_callback)(_recStream, nullptr, nullptr); 1121 1122 // Unset this here so that we don't get a TERMINATED callback 1123 LATE(pa_stream_set_state_callback)(_recStream, nullptr, nullptr); 1124 1125 if (LATE(pa_stream_get_state)(_recStream) != PA_STREAM_UNCONNECTED) { 1126 // Disconnect the stream 1127 if (LATE(pa_stream_disconnect)(_recStream) != PA_OK) { 1128 RTC_LOG(LS_ERROR) << "failed to disconnect rec stream, err=" 1129 << LATE(pa_context_errno)(_paContext); 1130 PaUnLock(); 1131 return -1; 1132 } 1133 1134 RTC_LOG(LS_VERBOSE) << "disconnected recording"; 1135 } 1136 1137 LATE(pa_stream_unref)(_recStream); 1138 _recStream = nullptr; 1139 1140 PaUnLock(); 1141 1142 // Provide the recStream to the mixer 1143 _mixerManager.SetRecStream(_recStream); 1144 1145 if (_recBuffer) { 1146 delete[] _recBuffer; 1147 _recBuffer = nullptr; 1148 } 1149 1150 return 0; 1151 } 1152 1153 bool AudioDeviceLinuxPulse::RecordingIsInitialized() const { 1154 RTC_DCHECK(thread_checker_.IsCurrent()); 1155 return (_recIsInitialized); 1156 } 1157 1158 bool AudioDeviceLinuxPulse::Recording() const { 1159 RTC_DCHECK(thread_checker_.IsCurrent()); 1160 return (_recording); 1161 } 1162 1163 bool AudioDeviceLinuxPulse::PlayoutIsInitialized() const { 1164 RTC_DCHECK(thread_checker_.IsCurrent()); 1165 return (_playIsInitialized); 1166 } 1167 1168 int32_t AudioDeviceLinuxPulse::StartPlayout() { 1169 RTC_DCHECK(thread_checker_.IsCurrent()); 1170 1171 if (!_playIsInitialized) { 1172 return -1; 1173 } 1174 1175 if (_playing) { 1176 return 0; 1177 } 1178 1179 // Set state to ensure that playout starts from the audio thread. 1180 { 1181 MutexLock lock(&mutex_); 1182 _startPlay = true; 1183 } 1184 1185 // Both `_startPlay` and `_playing` needs protction since they are also 1186 // accessed on the playout thread. 1187 1188 // The audio thread will signal when playout has started. 1189 _timeEventPlay.Set(); 1190 if (!_playStartEvent.Wait(TimeDelta::Seconds(10))) { 1191 { 1192 MutexLock lock(&mutex_); 1193 _startPlay = false; 1194 } 1195 StopPlayout(); 1196 RTC_LOG(LS_ERROR) << "failed to activate playout"; 1197 return -1; 1198 } 1199 1200 { 1201 MutexLock lock(&mutex_); 1202 if (_playing) { 1203 // The playing state is set by the audio thread after playout 1204 // has started. 1205 } else { 1206 RTC_LOG(LS_ERROR) << "failed to activate playing"; 1207 return -1; 1208 } 1209 } 1210 1211 return 0; 1212 } 1213 1214 int32_t AudioDeviceLinuxPulse::StopPlayout() { 1215 RTC_DCHECK(thread_checker_.IsCurrent()); 1216 MutexLock lock(&mutex_); 1217 1218 if (!_playIsInitialized) { 1219 return 0; 1220 } 1221 1222 if (_playStream == nullptr) { 1223 return -1; 1224 } 1225 1226 _playIsInitialized = false; 1227 _playing = false; 1228 _sndCardPlayDelay = 0; 1229 1230 RTC_LOG(LS_VERBOSE) << "stopping playback"; 1231 1232 // Stop Playout 1233 PaLock(); 1234 1235 DisableWriteCallback(); 1236 LATE(pa_stream_set_underflow_callback)(_playStream, nullptr, nullptr); 1237 1238 // Unset this here so that we don't get a TERMINATED callback 1239 LATE(pa_stream_set_state_callback)(_playStream, nullptr, nullptr); 1240 1241 if (LATE(pa_stream_get_state)(_playStream) != PA_STREAM_UNCONNECTED) { 1242 // Disconnect the stream 1243 if (LATE(pa_stream_disconnect)(_playStream) != PA_OK) { 1244 RTC_LOG(LS_ERROR) << "failed to disconnect play stream, err=" 1245 << LATE(pa_context_errno)(_paContext); 1246 PaUnLock(); 1247 return -1; 1248 } 1249 1250 RTC_LOG(LS_VERBOSE) << "disconnected playback"; 1251 } 1252 1253 LATE(pa_stream_unref)(_playStream); 1254 _playStream = nullptr; 1255 1256 PaUnLock(); 1257 1258 // Provide the playStream to the mixer 1259 _mixerManager.SetPlayStream(_playStream); 1260 1261 if (_playBuffer) { 1262 delete[] _playBuffer; 1263 _playBuffer = nullptr; 1264 } 1265 1266 return 0; 1267 } 1268 1269 int32_t AudioDeviceLinuxPulse::PlayoutDelay(uint16_t& delayMS) const { 1270 MutexLock lock(&mutex_); 1271 delayMS = (uint16_t)_sndCardPlayDelay; 1272 return 0; 1273 } 1274 1275 bool AudioDeviceLinuxPulse::Playing() const { 1276 RTC_DCHECK(thread_checker_.IsCurrent()); 1277 return (_playing); 1278 } 1279 1280 // ============================================================================ 1281 // Private Methods 1282 // ============================================================================ 1283 1284 void AudioDeviceLinuxPulse::PaContextStateCallback(pa_context* c, void* pThis) { 1285 static_cast<AudioDeviceLinuxPulse*>(pThis)->PaContextStateCallbackHandler(c); 1286 } 1287 1288 // ---------------------------------------------------------------------------- 1289 // PaSinkInfoCallback 1290 // ---------------------------------------------------------------------------- 1291 1292 void AudioDeviceLinuxPulse::PaSinkInfoCallback(pa_context* /*c*/, 1293 const pa_sink_info* i, 1294 int eol, 1295 void* pThis) { 1296 static_cast<AudioDeviceLinuxPulse*>(pThis)->PaSinkInfoCallbackHandler(i, eol); 1297 } 1298 1299 void AudioDeviceLinuxPulse::PaSourceInfoCallback(pa_context* /*c*/, 1300 const pa_source_info* i, 1301 int eol, 1302 void* pThis) { 1303 static_cast<AudioDeviceLinuxPulse*>(pThis)->PaSourceInfoCallbackHandler(i, 1304 eol); 1305 } 1306 1307 void AudioDeviceLinuxPulse::PaServerInfoCallback(pa_context* /*c*/, 1308 const pa_server_info* i, 1309 void* pThis) { 1310 static_cast<AudioDeviceLinuxPulse*>(pThis)->PaServerInfoCallbackHandler(i); 1311 } 1312 1313 void AudioDeviceLinuxPulse::PaStreamStateCallback(pa_stream* p, void* pThis) { 1314 static_cast<AudioDeviceLinuxPulse*>(pThis)->PaStreamStateCallbackHandler(p); 1315 } 1316 1317 void AudioDeviceLinuxPulse::PaContextStateCallbackHandler(pa_context* c) { 1318 RTC_LOG(LS_VERBOSE) << "context state cb"; 1319 1320 pa_context_state_t state = LATE(pa_context_get_state)(c); 1321 switch (state) { 1322 case PA_CONTEXT_UNCONNECTED: 1323 RTC_LOG(LS_VERBOSE) << "unconnected"; 1324 break; 1325 case PA_CONTEXT_CONNECTING: 1326 case PA_CONTEXT_AUTHORIZING: 1327 case PA_CONTEXT_SETTING_NAME: 1328 RTC_LOG(LS_VERBOSE) << "no state"; 1329 break; 1330 case PA_CONTEXT_FAILED: 1331 case PA_CONTEXT_TERMINATED: 1332 RTC_LOG(LS_VERBOSE) << "failed"; 1333 _paStateChanged = true; 1334 LATE(pa_threaded_mainloop_signal)(_paMainloop, 0); 1335 break; 1336 case PA_CONTEXT_READY: 1337 RTC_LOG(LS_VERBOSE) << "ready"; 1338 _paStateChanged = true; 1339 LATE(pa_threaded_mainloop_signal)(_paMainloop, 0); 1340 break; 1341 } 1342 } 1343 1344 void AudioDeviceLinuxPulse::PaSinkInfoCallbackHandler(const pa_sink_info* i, 1345 int eol) { 1346 if (eol) { 1347 // Signal that we are done 1348 LATE(pa_threaded_mainloop_signal)(_paMainloop, 0); 1349 return; 1350 } 1351 1352 if (_numPlayDevices == _deviceIndex) { 1353 // Convert the device index to the one of the sink 1354 _paDeviceIndex = i->index; 1355 1356 if (_playDeviceName) { 1357 // Copy the sink name 1358 strncpy(_playDeviceName, i->name, kAdmMaxDeviceNameSize); 1359 _playDeviceName[kAdmMaxDeviceNameSize - 1] = '\0'; 1360 } 1361 if (_playDisplayDeviceName) { 1362 // Copy the sink display name 1363 strncpy(_playDisplayDeviceName, i->description, kAdmMaxDeviceNameSize); 1364 _playDisplayDeviceName[kAdmMaxDeviceNameSize - 1] = '\0'; 1365 } 1366 } 1367 1368 _numPlayDevices++; 1369 } 1370 1371 void AudioDeviceLinuxPulse::PaSourceInfoCallbackHandler(const pa_source_info* i, 1372 int eol) { 1373 if (eol) { 1374 // Signal that we are done 1375 LATE(pa_threaded_mainloop_signal)(_paMainloop, 0); 1376 return; 1377 } 1378 1379 // We don't want to list output devices 1380 if (i->monitor_of_sink == PA_INVALID_INDEX) { 1381 if (_numRecDevices == _deviceIndex) { 1382 // Convert the device index to the one of the source 1383 _paDeviceIndex = i->index; 1384 1385 if (_recDeviceName) { 1386 // copy the source name 1387 strncpy(_recDeviceName, i->name, kAdmMaxDeviceNameSize); 1388 _recDeviceName[kAdmMaxDeviceNameSize - 1] = '\0'; 1389 } 1390 if (_recDisplayDeviceName) { 1391 // Copy the source display name 1392 strncpy(_recDisplayDeviceName, i->description, kAdmMaxDeviceNameSize); 1393 _recDisplayDeviceName[kAdmMaxDeviceNameSize - 1] = '\0'; 1394 } 1395 } 1396 1397 _numRecDevices++; 1398 } 1399 } 1400 1401 void AudioDeviceLinuxPulse::PaServerInfoCallbackHandler( 1402 const pa_server_info* i) { 1403 // Use PA native sampling rate 1404 sample_rate_hz_ = i->sample_spec.rate; 1405 1406 // Copy the PA server version 1407 strncpy(_paServerVersion, i->server_version, 31); 1408 _paServerVersion[31] = '\0'; 1409 1410 if (_recDisplayDeviceName) { 1411 // Copy the source name 1412 strncpy(_recDisplayDeviceName, i->default_source_name, 1413 kAdmMaxDeviceNameSize); 1414 _recDisplayDeviceName[kAdmMaxDeviceNameSize - 1] = '\0'; 1415 } 1416 1417 if (_playDisplayDeviceName) { 1418 // Copy the sink name 1419 strncpy(_playDisplayDeviceName, i->default_sink_name, 1420 kAdmMaxDeviceNameSize); 1421 _playDisplayDeviceName[kAdmMaxDeviceNameSize - 1] = '\0'; 1422 } 1423 1424 LATE(pa_threaded_mainloop_signal)(_paMainloop, 0); 1425 } 1426 1427 void AudioDeviceLinuxPulse::PaStreamStateCallbackHandler(pa_stream* p) { 1428 RTC_LOG(LS_VERBOSE) << "stream state cb"; 1429 1430 pa_stream_state_t state = LATE(pa_stream_get_state)(p); 1431 switch (state) { 1432 case PA_STREAM_UNCONNECTED: 1433 RTC_LOG(LS_VERBOSE) << "unconnected"; 1434 break; 1435 case PA_STREAM_CREATING: 1436 RTC_LOG(LS_VERBOSE) << "creating"; 1437 break; 1438 case PA_STREAM_FAILED: 1439 case PA_STREAM_TERMINATED: 1440 RTC_LOG(LS_VERBOSE) << "failed"; 1441 break; 1442 case PA_STREAM_READY: 1443 RTC_LOG(LS_VERBOSE) << "ready"; 1444 break; 1445 } 1446 1447 LATE(pa_threaded_mainloop_signal)(_paMainloop, 0); 1448 } 1449 1450 int32_t AudioDeviceLinuxPulse::CheckPulseAudioVersion() { 1451 PaLock(); 1452 1453 pa_operation* paOperation = nullptr; 1454 1455 // get the server info and update deviceName 1456 paOperation = 1457 LATE(pa_context_get_server_info)(_paContext, PaServerInfoCallback, this); 1458 1459 WaitForOperationCompletion(paOperation); 1460 1461 PaUnLock(); 1462 1463 RTC_LOG(LS_VERBOSE) << "checking PulseAudio version: " << _paServerVersion; 1464 1465 return 0; 1466 } 1467 1468 int32_t AudioDeviceLinuxPulse::InitSamplingFrequency() { 1469 PaLock(); 1470 1471 pa_operation* paOperation = nullptr; 1472 1473 // Get the server info and update sample_rate_hz_ 1474 paOperation = 1475 LATE(pa_context_get_server_info)(_paContext, PaServerInfoCallback, this); 1476 1477 WaitForOperationCompletion(paOperation); 1478 1479 PaUnLock(); 1480 1481 return 0; 1482 } 1483 1484 int32_t AudioDeviceLinuxPulse::GetDefaultDeviceInfo(bool recDevice, 1485 char* name, 1486 uint16_t& index) { 1487 char tmpName[kAdmMaxDeviceNameSize] = {0}; 1488 // subtract length of "default: " 1489 uint16_t nameLen = kAdmMaxDeviceNameSize - 9; 1490 char* pName = nullptr; 1491 1492 if (name) { 1493 // Add "default: " 1494 strcpy(name, "default: "); 1495 pName = &name[9]; 1496 } 1497 1498 // Tell the callback that we want 1499 // the name for this device 1500 if (recDevice) { 1501 _recDisplayDeviceName = tmpName; 1502 } else { 1503 _playDisplayDeviceName = tmpName; 1504 } 1505 1506 // Set members 1507 _paDeviceIndex = -1; 1508 _deviceIndex = 0; 1509 _numPlayDevices = 0; 1510 _numRecDevices = 0; 1511 1512 PaLock(); 1513 1514 pa_operation* paOperation = nullptr; 1515 1516 // Get the server info and update deviceName 1517 paOperation = 1518 LATE(pa_context_get_server_info)(_paContext, PaServerInfoCallback, this); 1519 1520 WaitForOperationCompletion(paOperation); 1521 1522 // Get the device index 1523 if (recDevice) { 1524 paOperation = LATE(pa_context_get_source_info_by_name)( 1525 _paContext, (char*)tmpName, PaSourceInfoCallback, this); 1526 } else { 1527 paOperation = LATE(pa_context_get_sink_info_by_name)( 1528 _paContext, (char*)tmpName, PaSinkInfoCallback, this); 1529 } 1530 1531 WaitForOperationCompletion(paOperation); 1532 1533 PaUnLock(); 1534 1535 // Set the index 1536 index = _paDeviceIndex; 1537 1538 if (name) { 1539 // Copy to name string 1540 strncpy(pName, tmpName, nameLen); 1541 } 1542 1543 // Clear members 1544 _playDisplayDeviceName = nullptr; 1545 _recDisplayDeviceName = nullptr; 1546 _paDeviceIndex = -1; 1547 _deviceIndex = -1; 1548 _numPlayDevices = 0; 1549 _numRecDevices = 0; 1550 1551 return 0; 1552 } 1553 1554 int32_t AudioDeviceLinuxPulse::InitPulseAudio() { 1555 int retVal = 0; 1556 1557 // Load libpulse 1558 if (!GetPulseSymbolTable()->Load()) { 1559 // Most likely the Pulse library and sound server are not installed on 1560 // this system 1561 RTC_LOG(LS_ERROR) << "failed to load symbol table"; 1562 return -1; 1563 } 1564 1565 // Create a mainloop API and connection to the default server 1566 // the mainloop is the internal asynchronous API event loop 1567 if (_paMainloop) { 1568 RTC_LOG(LS_ERROR) << "PA mainloop has already existed"; 1569 return -1; 1570 } 1571 _paMainloop = LATE(pa_threaded_mainloop_new)(); 1572 if (!_paMainloop) { 1573 RTC_LOG(LS_ERROR) << "could not create mainloop"; 1574 return -1; 1575 } 1576 1577 // Start the threaded main loop 1578 retVal = LATE(pa_threaded_mainloop_start)(_paMainloop); 1579 if (retVal != PA_OK) { 1580 RTC_LOG(LS_ERROR) << "failed to start main loop, error=" << retVal; 1581 return -1; 1582 } 1583 1584 RTC_LOG(LS_VERBOSE) << "mainloop running!"; 1585 1586 PaLock(); 1587 1588 _paMainloopApi = LATE(pa_threaded_mainloop_get_api)(_paMainloop); 1589 if (!_paMainloopApi) { 1590 RTC_LOG(LS_ERROR) << "could not create mainloop API"; 1591 PaUnLock(); 1592 return -1; 1593 } 1594 1595 // Create a new PulseAudio context 1596 if (_paContext) { 1597 RTC_LOG(LS_ERROR) << "PA context has already existed"; 1598 PaUnLock(); 1599 return -1; 1600 } 1601 _paContext = LATE(pa_context_new)(_paMainloopApi, "WEBRTC VoiceEngine"); 1602 1603 if (!_paContext) { 1604 RTC_LOG(LS_ERROR) << "could not create context"; 1605 PaUnLock(); 1606 return -1; 1607 } 1608 1609 // Set state callback function 1610 LATE(pa_context_set_state_callback)(_paContext, PaContextStateCallback, this); 1611 1612 // Connect the context to a server (default) 1613 _paStateChanged = false; 1614 retVal = LATE(pa_context_connect)(_paContext, nullptr, PA_CONTEXT_NOAUTOSPAWN, 1615 nullptr); 1616 1617 if (retVal != PA_OK) { 1618 RTC_LOG(LS_ERROR) << "failed to connect context, error=" << retVal; 1619 PaUnLock(); 1620 return -1; 1621 } 1622 1623 // Wait for state change 1624 while (!_paStateChanged) { 1625 LATE(pa_threaded_mainloop_wait)(_paMainloop); 1626 } 1627 1628 // Now check to see what final state we reached. 1629 pa_context_state_t state = LATE(pa_context_get_state)(_paContext); 1630 1631 if (state != PA_CONTEXT_READY) { 1632 if (state == PA_CONTEXT_FAILED) { 1633 RTC_LOG(LS_ERROR) << "failed to connect to PulseAudio sound server"; 1634 } else if (state == PA_CONTEXT_TERMINATED) { 1635 RTC_LOG(LS_ERROR) << "PulseAudio connection terminated early"; 1636 } else { 1637 // Shouldn't happen, because we only signal on one of those three 1638 // states 1639 RTC_LOG(LS_ERROR) << "unknown problem connecting to PulseAudio"; 1640 } 1641 PaUnLock(); 1642 return -1; 1643 } 1644 1645 PaUnLock(); 1646 1647 // Give the objects to the mixer manager 1648 _mixerManager.SetPulseAudioObjects(_paMainloop, _paContext); 1649 1650 // Check the version 1651 if (CheckPulseAudioVersion() < 0) { 1652 RTC_LOG(LS_ERROR) << "PulseAudio version " << _paServerVersion 1653 << " not supported"; 1654 return -1; 1655 } 1656 1657 // Initialize sampling frequency 1658 if (InitSamplingFrequency() < 0 || sample_rate_hz_ == 0) { 1659 RTC_LOG(LS_ERROR) << "failed to initialize sampling frequency, set to " 1660 << sample_rate_hz_ << " Hz"; 1661 return -1; 1662 } 1663 1664 return 0; 1665 } 1666 1667 int32_t AudioDeviceLinuxPulse::TerminatePulseAudio() { 1668 // Do nothing if the instance doesn't exist 1669 // likely GetPulseSymbolTable.Load() fails 1670 if (!_paMainloop) { 1671 return 0; 1672 } 1673 1674 PaLock(); 1675 1676 // Disconnect the context 1677 if (_paContext) { 1678 LATE(pa_context_disconnect)(_paContext); 1679 } 1680 1681 // Unreference the context 1682 if (_paContext) { 1683 LATE(pa_context_unref)(_paContext); 1684 } 1685 1686 PaUnLock(); 1687 _paContext = nullptr; 1688 1689 // Stop the threaded main loop 1690 if (_paMainloop) { 1691 LATE(pa_threaded_mainloop_stop)(_paMainloop); 1692 } 1693 1694 // Free the mainloop 1695 if (_paMainloop) { 1696 LATE(pa_threaded_mainloop_free)(_paMainloop); 1697 } 1698 1699 _paMainloop = nullptr; 1700 1701 RTC_LOG(LS_VERBOSE) << "PulseAudio terminated"; 1702 1703 return 0; 1704 } 1705 1706 void AudioDeviceLinuxPulse::PaLock() { 1707 LATE(pa_threaded_mainloop_lock)(_paMainloop); 1708 } 1709 1710 void AudioDeviceLinuxPulse::PaUnLock() { 1711 LATE(pa_threaded_mainloop_unlock)(_paMainloop); 1712 } 1713 1714 void AudioDeviceLinuxPulse::WaitForOperationCompletion( 1715 pa_operation* paOperation) const { 1716 if (!paOperation) { 1717 RTC_LOG(LS_ERROR) << "paOperation NULL in WaitForOperationCompletion"; 1718 return; 1719 } 1720 1721 while (LATE(pa_operation_get_state)(paOperation) == PA_OPERATION_RUNNING) { 1722 LATE(pa_threaded_mainloop_wait)(_paMainloop); 1723 } 1724 1725 LATE(pa_operation_unref)(paOperation); 1726 } 1727 1728 // ============================================================================ 1729 // Thread Methods 1730 // ============================================================================ 1731 1732 void AudioDeviceLinuxPulse::EnableWriteCallback() { 1733 if (LATE(pa_stream_get_state)(_playStream) == PA_STREAM_READY) { 1734 // May already have available space. Must check. 1735 _tempBufferSpace = LATE(pa_stream_writable_size)(_playStream); 1736 if (_tempBufferSpace > 0) { 1737 // Yup, there is already space available, so if we register a 1738 // write callback then it will not receive any event. So dispatch 1739 // one ourself instead. 1740 _timeEventPlay.Set(); 1741 return; 1742 } 1743 } 1744 1745 LATE(pa_stream_set_write_callback)(_playStream, &PaStreamWriteCallback, this); 1746 } 1747 1748 void AudioDeviceLinuxPulse::DisableWriteCallback() { 1749 LATE(pa_stream_set_write_callback)(_playStream, nullptr, nullptr); 1750 } 1751 1752 void AudioDeviceLinuxPulse::PaStreamWriteCallback(pa_stream* /*unused*/, 1753 size_t buffer_space, 1754 void* pThis) { 1755 static_cast<AudioDeviceLinuxPulse*>(pThis)->PaStreamWriteCallbackHandler( 1756 buffer_space); 1757 } 1758 1759 void AudioDeviceLinuxPulse::PaStreamWriteCallbackHandler(size_t bufferSpace) { 1760 _tempBufferSpace = bufferSpace; 1761 1762 // Since we write the data asynchronously on a different thread, we have 1763 // to temporarily disable the write callback or else Pulse will call it 1764 // continuously until we write the data. We re-enable it below. 1765 DisableWriteCallback(); 1766 _timeEventPlay.Set(); 1767 } 1768 1769 void AudioDeviceLinuxPulse::PaStreamUnderflowCallback(pa_stream* /*unused*/, 1770 void* pThis) { 1771 static_cast<AudioDeviceLinuxPulse*>(pThis) 1772 ->PaStreamUnderflowCallbackHandler(); 1773 } 1774 1775 void AudioDeviceLinuxPulse::PaStreamUnderflowCallbackHandler() { 1776 RTC_LOG(LS_WARNING) << "Playout underflow"; 1777 1778 if (_configuredLatencyPlay == WEBRTC_PA_NO_LATENCY_REQUIREMENTS) { 1779 // We didn't configure a pa_buffer_attr before, so switching to 1780 // one now would be questionable. 1781 return; 1782 } 1783 1784 // Otherwise reconfigure the stream with a higher target latency. 1785 1786 const pa_sample_spec* spec = LATE(pa_stream_get_sample_spec)(_playStream); 1787 if (!spec) { 1788 RTC_LOG(LS_ERROR) << "pa_stream_get_sample_spec()"; 1789 return; 1790 } 1791 1792 size_t bytesPerSec = LATE(pa_bytes_per_second)(spec); 1793 uint32_t newLatency = 1794 _configuredLatencyPlay + bytesPerSec * 1795 WEBRTC_PA_PLAYBACK_LATENCY_INCREMENT_MSECS / 1796 WEBRTC_PA_MSECS_PER_SEC; 1797 1798 // Set the play buffer attributes 1799 _playBufferAttr.maxlength = newLatency; 1800 _playBufferAttr.tlength = newLatency; 1801 _playBufferAttr.minreq = newLatency / WEBRTC_PA_PLAYBACK_REQUEST_FACTOR; 1802 _playBufferAttr.prebuf = _playBufferAttr.tlength - _playBufferAttr.minreq; 1803 1804 pa_operation* op = LATE(pa_stream_set_buffer_attr)( 1805 _playStream, &_playBufferAttr, nullptr, nullptr); 1806 if (!op) { 1807 RTC_LOG(LS_ERROR) << "pa_stream_set_buffer_attr()"; 1808 return; 1809 } 1810 1811 // Don't need to wait for this to complete. 1812 LATE(pa_operation_unref)(op); 1813 1814 // Save the new latency in case we underflow again. 1815 _configuredLatencyPlay = newLatency; 1816 } 1817 1818 void AudioDeviceLinuxPulse::EnableReadCallback() { 1819 LATE(pa_stream_set_read_callback)(_recStream, &PaStreamReadCallback, this); 1820 } 1821 1822 void AudioDeviceLinuxPulse::DisableReadCallback() { 1823 LATE(pa_stream_set_read_callback)(_recStream, nullptr, nullptr); 1824 } 1825 1826 void AudioDeviceLinuxPulse::PaStreamReadCallback(pa_stream* /*unused1*/, 1827 size_t /*unused2*/, 1828 void* pThis) { 1829 static_cast<AudioDeviceLinuxPulse*>(pThis)->PaStreamReadCallbackHandler(); 1830 } 1831 1832 void AudioDeviceLinuxPulse::PaStreamReadCallbackHandler() { 1833 // We get the data pointer and size now in order to save one Lock/Unlock 1834 // in the worker thread. 1835 if (LATE(pa_stream_peek)(_recStream, &_tempSampleData, 1836 &_tempSampleDataSize) != 0) { 1837 RTC_LOG(LS_ERROR) << "Can't read data!"; 1838 return; 1839 } 1840 1841 // Since we consume the data asynchronously on a different thread, we have 1842 // to temporarily disable the read callback or else Pulse will call it 1843 // continuously until we consume the data. We re-enable it below. 1844 DisableReadCallback(); 1845 _timeEventRec.Set(); 1846 } 1847 1848 void AudioDeviceLinuxPulse::PaStreamOverflowCallback(pa_stream* /*unused*/, 1849 void* pThis) { 1850 static_cast<AudioDeviceLinuxPulse*>(pThis)->PaStreamOverflowCallbackHandler(); 1851 } 1852 1853 void AudioDeviceLinuxPulse::PaStreamOverflowCallbackHandler() { 1854 RTC_LOG(LS_WARNING) << "Recording overflow"; 1855 } 1856 1857 int32_t AudioDeviceLinuxPulse::LatencyUsecs(pa_stream* stream) { 1858 if (!WEBRTC_PA_REPORT_LATENCY) { 1859 return 0; 1860 } 1861 1862 if (!stream) { 1863 return 0; 1864 } 1865 1866 pa_usec_t latency; 1867 int negative; 1868 if (LATE(pa_stream_get_latency)(stream, &latency, &negative) != 0) { 1869 RTC_LOG(LS_ERROR) << "Can't query latency"; 1870 // We'd rather continue playout/capture with an incorrect delay than 1871 // stop it altogether, so return a valid value. 1872 return 0; 1873 } 1874 1875 if (negative) { 1876 RTC_LOG(LS_VERBOSE) 1877 << "warning: pa_stream_get_latency reported negative delay"; 1878 1879 // The delay can be negative for monitoring streams if the captured 1880 // samples haven't been played yet. In such a case, "latency" 1881 // contains the magnitude, so we must negate it to get the real value. 1882 int32_t tmpLatency = (int32_t)-latency; 1883 if (tmpLatency < 0) { 1884 // Make sure that we don't use a negative delay. 1885 tmpLatency = 0; 1886 } 1887 1888 return tmpLatency; 1889 } else { 1890 return (int32_t)latency; 1891 } 1892 } 1893 1894 int32_t AudioDeviceLinuxPulse::ReadRecordedData(const void* bufferData, 1895 size_t bufferSize) 1896 RTC_EXCLUSIVE_LOCKS_REQUIRED(mutex_) { 1897 size_t size = bufferSize; 1898 uint32_t numRecSamples = _recordBufferSize / (2 * _recChannels); 1899 1900 // Account for the peeked data and the used data. 1901 uint32_t recDelay = 1902 (uint32_t)((LatencyUsecs(_recStream) / 1000) + 1903 10 * ((size + _recordBufferUsed) / _recordBufferSize)); 1904 1905 if (_playStream) { 1906 // Get the playout delay. 1907 _sndCardPlayDelay = (uint32_t)(LatencyUsecs(_playStream) / 1000); 1908 } 1909 1910 if (_recordBufferUsed > 0) { 1911 // Have to copy to the buffer until it is full. 1912 size_t copy = _recordBufferSize - _recordBufferUsed; 1913 if (size < copy) { 1914 copy = size; 1915 } 1916 1917 memcpy(&_recBuffer[_recordBufferUsed], bufferData, copy); 1918 _recordBufferUsed += copy; 1919 bufferData = static_cast<const char*>(bufferData) + copy; 1920 size -= copy; 1921 1922 if (_recordBufferUsed != _recordBufferSize) { 1923 // Not enough data yet to pass to VoE. 1924 return 0; 1925 } 1926 1927 // Provide data to VoiceEngine. 1928 if (ProcessRecordedData(_recBuffer, numRecSamples, recDelay) == -1) { 1929 // We have stopped recording. 1930 return -1; 1931 } 1932 1933 _recordBufferUsed = 0; 1934 } 1935 1936 // Now process full 10ms sample sets directly from the input. 1937 while (size >= _recordBufferSize) { 1938 // Provide data to VoiceEngine. 1939 if (ProcessRecordedData(static_cast<int8_t*>(const_cast<void*>(bufferData)), 1940 numRecSamples, recDelay) == -1) { 1941 // We have stopped recording. 1942 return -1; 1943 } 1944 1945 bufferData = static_cast<const char*>(bufferData) + _recordBufferSize; 1946 size -= _recordBufferSize; 1947 1948 // We have consumed 10ms of data. 1949 recDelay -= 10; 1950 } 1951 1952 // Now save any leftovers for later. 1953 if (size > 0) { 1954 memcpy(_recBuffer, bufferData, size); 1955 _recordBufferUsed = size; 1956 } 1957 1958 return 0; 1959 } 1960 1961 int32_t AudioDeviceLinuxPulse::ProcessRecordedData(int8_t* bufferData, 1962 uint32_t bufferSizeInSamples, 1963 uint32_t recDelay) 1964 RTC_EXCLUSIVE_LOCKS_REQUIRED(mutex_) { 1965 _ptrAudioBuffer->SetRecordedBuffer(bufferData, bufferSizeInSamples); 1966 1967 // TODO(andrew): this is a temporary hack, to avoid non-causal far- and 1968 // near-end signals at the AEC for PulseAudio. I think the system delay is 1969 // being correctly calculated here, but for legacy reasons we add +10 ms 1970 // to the value in the AEC. The real fix will be part of a larger 1971 // investigation into managing system delay in the AEC. 1972 if (recDelay > 10) 1973 recDelay -= 10; 1974 else 1975 recDelay = 0; 1976 _ptrAudioBuffer->SetVQEData(_sndCardPlayDelay, recDelay); 1977 _ptrAudioBuffer->SetTypingStatus(KeyPressed()); 1978 // Deliver recorded samples at specified sample rate, 1979 // mic level etc. to the observer using callback. 1980 UnLock(); 1981 _ptrAudioBuffer->DeliverRecordedData(); 1982 Lock(); 1983 1984 // We have been unlocked - check the flag again. 1985 if (!_recording) { 1986 return -1; 1987 } 1988 1989 return 0; 1990 } 1991 1992 bool AudioDeviceLinuxPulse::PlayThreadProcess() { 1993 if (!_timeEventPlay.Wait(TimeDelta::Seconds(1))) { 1994 return true; 1995 } 1996 1997 MutexLock lock(&mutex_); 1998 1999 if (quit_) { 2000 return false; 2001 } 2002 2003 if (_startPlay) { 2004 RTC_LOG(LS_VERBOSE) << "_startPlay true, performing initial actions"; 2005 2006 _startPlay = false; 2007 _playDeviceName = nullptr; 2008 2009 // Set if not default device 2010 if (_outputDeviceIndex > 0) { 2011 // Get the playout device name 2012 _playDeviceName = new char[kAdmMaxDeviceNameSize]; 2013 _deviceIndex = _outputDeviceIndex; 2014 PlayoutDevices(); 2015 } 2016 2017 // Start muted only supported on 0.9.11 and up 2018 if (LATE(pa_context_get_protocol_version)(_paContext) >= 2019 WEBRTC_PA_ADJUST_LATENCY_PROTOCOL_VERSION) { 2020 // Get the currently saved speaker mute status 2021 // and set the initial mute status accordingly 2022 bool enabled(false); 2023 _mixerManager.SpeakerMute(enabled); 2024 if (enabled) { 2025 _playStreamFlags |= PA_STREAM_START_MUTED; 2026 } 2027 } 2028 2029 // Get the currently saved speaker volume 2030 uint32_t volume = 0; 2031 if (update_speaker_volume_at_startup_) 2032 _mixerManager.SpeakerVolume(volume); 2033 2034 PaLock(); 2035 2036 // NULL gives PA the choice of startup volume. 2037 pa_cvolume* ptr_cvolume = nullptr; 2038 if (update_speaker_volume_at_startup_) { 2039 pa_cvolume cVolumes; 2040 ptr_cvolume = &cVolumes; 2041 2042 // Set the same volume for all channels 2043 const pa_sample_spec* spec = LATE(pa_stream_get_sample_spec)(_playStream); 2044 LATE(pa_cvolume_set)(&cVolumes, spec->channels, volume); 2045 update_speaker_volume_at_startup_ = false; 2046 } 2047 2048 // Connect the stream to a sink 2049 if (LATE(pa_stream_connect_playback)(_playStream, _playDeviceName, 2050 &_playBufferAttr, 2051 (pa_stream_flags_t)_playStreamFlags, 2052 ptr_cvolume, nullptr) != PA_OK) { 2053 RTC_LOG(LS_ERROR) << "failed to connect play stream, err=" 2054 << LATE(pa_context_errno)(_paContext); 2055 } 2056 2057 RTC_LOG(LS_VERBOSE) << "play stream connected"; 2058 2059 // Wait for state change 2060 while (LATE(pa_stream_get_state)(_playStream) != PA_STREAM_READY) { 2061 LATE(pa_threaded_mainloop_wait)(_paMainloop); 2062 } 2063 2064 RTC_LOG(LS_VERBOSE) << "play stream ready"; 2065 2066 // We can now handle write callbacks 2067 EnableWriteCallback(); 2068 2069 PaUnLock(); 2070 2071 // Clear device name 2072 if (_playDeviceName) { 2073 delete[] _playDeviceName; 2074 _playDeviceName = nullptr; 2075 } 2076 2077 _playing = true; 2078 _playStartEvent.Set(); 2079 2080 return true; 2081 } 2082 2083 if (_playing) { 2084 if (!_recording) { 2085 // Update the playout delay 2086 _sndCardPlayDelay = (uint32_t)(LatencyUsecs(_playStream) / 1000); 2087 } 2088 2089 if (_playbackBufferUnused < _playbackBufferSize) { 2090 size_t write = _playbackBufferSize - _playbackBufferUnused; 2091 if (_tempBufferSpace < write) { 2092 write = _tempBufferSpace; 2093 } 2094 2095 PaLock(); 2096 if (LATE(pa_stream_write)( 2097 _playStream, (void*)&_playBuffer[_playbackBufferUnused], write, 2098 nullptr, (int64_t)0, PA_SEEK_RELATIVE) != PA_OK) { 2099 _writeErrors++; 2100 if (_writeErrors > 10) { 2101 RTC_LOG(LS_ERROR) << "Playout error: _writeErrors=" << _writeErrors 2102 << ", error=" << LATE(pa_context_errno)(_paContext); 2103 _writeErrors = 0; 2104 } 2105 } 2106 PaUnLock(); 2107 2108 _playbackBufferUnused += write; 2109 _tempBufferSpace -= write; 2110 } 2111 2112 uint32_t numPlaySamples = _playbackBufferSize / (2 * _playChannels); 2113 // Might have been reduced to zero by the above. 2114 if (_tempBufferSpace > 0) { 2115 // Ask for new PCM data to be played out using the 2116 // AudioDeviceBuffer ensure that this callback is executed 2117 // without taking the audio-thread lock. 2118 UnLock(); 2119 RTC_LOG(LS_VERBOSE) << "requesting data"; 2120 uint32_t nSamples = _ptrAudioBuffer->RequestPlayoutData(numPlaySamples); 2121 Lock(); 2122 2123 // We have been unlocked - check the flag again. 2124 if (!_playing) { 2125 return true; 2126 } 2127 2128 nSamples = _ptrAudioBuffer->GetPlayoutData(_playBuffer); 2129 if (nSamples != numPlaySamples) { 2130 RTC_LOG(LS_ERROR) << "invalid number of output samples(" << nSamples 2131 << ")"; 2132 } 2133 2134 size_t write = _playbackBufferSize; 2135 if (_tempBufferSpace < write) { 2136 write = _tempBufferSpace; 2137 } 2138 2139 RTC_LOG(LS_VERBOSE) << "will write"; 2140 PaLock(); 2141 if (LATE(pa_stream_write)(_playStream, (void*)&_playBuffer[0], write, 2142 nullptr, (int64_t)0, 2143 PA_SEEK_RELATIVE) != PA_OK) { 2144 _writeErrors++; 2145 if (_writeErrors > 10) { 2146 RTC_LOG(LS_ERROR) << "Playout error: _writeErrors=" << _writeErrors 2147 << ", error=" << LATE(pa_context_errno)(_paContext); 2148 _writeErrors = 0; 2149 } 2150 } 2151 PaUnLock(); 2152 2153 _playbackBufferUnused = write; 2154 } 2155 2156 _tempBufferSpace = 0; 2157 PaLock(); 2158 EnableWriteCallback(); 2159 PaUnLock(); 2160 2161 } // _playing 2162 2163 return true; 2164 } 2165 2166 bool AudioDeviceLinuxPulse::RecThreadProcess() { 2167 if (!_timeEventRec.Wait(TimeDelta::Seconds(1))) { 2168 return true; 2169 } 2170 2171 MutexLock lock(&mutex_); 2172 if (quit_) { 2173 return false; 2174 } 2175 if (_startRec) { 2176 RTC_LOG(LS_VERBOSE) << "_startRec true, performing initial actions"; 2177 2178 _recDeviceName = nullptr; 2179 2180 // Set if not default device 2181 if (_inputDeviceIndex > 0) { 2182 // Get the recording device name 2183 _recDeviceName = new char[kAdmMaxDeviceNameSize]; 2184 _deviceIndex = _inputDeviceIndex; 2185 RecordingDevices(); 2186 } 2187 2188 PaLock(); 2189 2190 RTC_LOG(LS_VERBOSE) << "connecting stream"; 2191 2192 // Connect the stream to a source 2193 if (LATE(pa_stream_connect_record)( 2194 _recStream, _recDeviceName, &_recBufferAttr, 2195 (pa_stream_flags_t)_recStreamFlags) != PA_OK) { 2196 RTC_LOG(LS_ERROR) << "failed to connect rec stream, err=" 2197 << LATE(pa_context_errno)(_paContext); 2198 } 2199 2200 RTC_LOG(LS_VERBOSE) << "connected"; 2201 2202 // Wait for state change 2203 while (LATE(pa_stream_get_state)(_recStream) != PA_STREAM_READY) { 2204 LATE(pa_threaded_mainloop_wait)(_paMainloop); 2205 } 2206 2207 RTC_LOG(LS_VERBOSE) << "done"; 2208 2209 // We can now handle read callbacks 2210 EnableReadCallback(); 2211 2212 PaUnLock(); 2213 2214 // Clear device name 2215 if (_recDeviceName) { 2216 delete[] _recDeviceName; 2217 _recDeviceName = nullptr; 2218 } 2219 2220 _startRec = false; 2221 _recording = true; 2222 _recStartEvent.Set(); 2223 2224 return true; 2225 } 2226 2227 if (_recording) { 2228 // Read data and provide it to VoiceEngine 2229 if (ReadRecordedData(_tempSampleData, _tempSampleDataSize) == -1) { 2230 return true; 2231 } 2232 2233 _tempSampleData = nullptr; 2234 _tempSampleDataSize = 0; 2235 2236 PaLock(); 2237 while (true) { 2238 // Ack the last thing we read 2239 if (LATE(pa_stream_drop)(_recStream) != 0) { 2240 RTC_LOG(LS_WARNING) 2241 << "failed to drop, err=" << LATE(pa_context_errno)(_paContext); 2242 } 2243 2244 if (LATE(pa_stream_readable_size)(_recStream) <= 0) { 2245 // Then that was all the data 2246 break; 2247 } 2248 2249 // Else more data. 2250 const void* sampleData; 2251 size_t sampleDataSize; 2252 2253 if (LATE(pa_stream_peek)(_recStream, &sampleData, &sampleDataSize) != 0) { 2254 RTC_LOG(LS_ERROR) << "RECORD_ERROR, error = " 2255 << LATE(pa_context_errno)(_paContext); 2256 break; 2257 } 2258 2259 // Drop lock for sigslot dispatch, which could take a while. 2260 PaUnLock(); 2261 // Read data and provide it to VoiceEngine 2262 if (ReadRecordedData(sampleData, sampleDataSize) == -1) { 2263 return true; 2264 } 2265 PaLock(); 2266 2267 // Return to top of loop for the ack and the check for more data. 2268 } 2269 2270 EnableReadCallback(); 2271 PaUnLock(); 2272 2273 } // _recording 2274 2275 return true; 2276 } 2277 2278 bool AudioDeviceLinuxPulse::KeyPressed() const { 2279 #if defined(WEBRTC_USE_X11) 2280 char szKey[32]; 2281 unsigned int i = 0; 2282 char state = 0; 2283 2284 if (!_XDisplay) 2285 return false; 2286 2287 // Check key map status 2288 XQueryKeymap(_XDisplay, szKey); 2289 2290 // A bit change in keymap means a key is pressed 2291 for (i = 0; i < sizeof(szKey); i++) 2292 state |= (szKey[i] ^ _oldKeyState[i]) & szKey[i]; 2293 2294 // Save old state 2295 memcpy((char*)_oldKeyState, (char*)szKey, sizeof(_oldKeyState)); 2296 return (state != 0); 2297 #else 2298 return false; 2299 #endif 2300 } 2301 } // namespace webrtc