tor-browser

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

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