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