1b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/* 2b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. 3b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * 4b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * Use of this source code is governed by a BSD-style license 5b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * that can be found in the LICENSE file in the root of the source 6b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * tree. An additional intellectual property rights grant can be found 7b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * in the file PATENTS. All contributing project authors may 8b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * be found in the AUTHORS file in the root of the source tree. 9b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org */ 10b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 113f45c2e0ac4cb280f941efa3a3476895795e3dd6pbos@webrtc.org#include <assert.h> 12b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 13bc669ace8f09d73e95f923253ecdadd366f9b7f1pbos@webrtc.org#include "webrtc/modules/audio_device/audio_device_config.h" 14bc669ace8f09d73e95f923253ecdadd366f9b7f1pbos@webrtc.org#include "webrtc/modules/audio_device/audio_device_utility.h" 15bc669ace8f09d73e95f923253ecdadd366f9b7f1pbos@webrtc.org#include "webrtc/modules/audio_device/linux/audio_device_alsa_linux.h" 16b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 17bc669ace8f09d73e95f923253ecdadd366f9b7f1pbos@webrtc.org#include "webrtc/system_wrappers/interface/event_wrapper.h" 18bc669ace8f09d73e95f923253ecdadd366f9b7f1pbos@webrtc.org#include "webrtc/system_wrappers/interface/sleep.h" 19bc669ace8f09d73e95f923253ecdadd366f9b7f1pbos@webrtc.org#include "webrtc/system_wrappers/interface/thread_wrapper.h" 20bc669ace8f09d73e95f923253ecdadd366f9b7f1pbos@webrtc.org#include "webrtc/system_wrappers/interface/trace.h" 21b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 22b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgwebrtc_adm_linux_alsa::AlsaSymbolTable AlsaSymbolTable; 23b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 24b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// Accesses ALSA functions through our late-binding symbol table instead of 25b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// directly. This way we don't have to link to libasound, which means our binary 26b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// will work on systems that don't have it. 27b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#define LATE(sym) \ 28b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org LATESYM_GET(webrtc_adm_linux_alsa::AlsaSymbolTable, &AlsaSymbolTable, sym) 29b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 30b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// Redefine these here to be able to do late-binding 31b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#undef snd_ctl_card_info_alloca 32b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#define snd_ctl_card_info_alloca(ptr) \ 33b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org do { *ptr = (snd_ctl_card_info_t *) \ 34b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org __builtin_alloca (LATE(snd_ctl_card_info_sizeof)()); \ 35b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org memset(*ptr, 0, LATE(snd_ctl_card_info_sizeof)()); } while (0) 36b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 37b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#undef snd_pcm_info_alloca 38b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#define snd_pcm_info_alloca(pInfo) \ 39b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org do { *pInfo = (snd_pcm_info_t *) \ 40b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org __builtin_alloca (LATE(snd_pcm_info_sizeof)()); \ 41b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org memset(*pInfo, 0, LATE(snd_pcm_info_sizeof)()); } while (0) 42b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 43b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// snd_lib_error_handler_t 44b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgvoid WebrtcAlsaErrorHandler(const char *file, 45b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org int line, 46b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org const char *function, 47b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org int err, 48b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org const char *fmt,...){}; 49b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 50b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgnamespace webrtc 51b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 52b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgstatic const unsigned int ALSA_PLAYOUT_FREQ = 48000; 53b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgstatic const unsigned int ALSA_PLAYOUT_CH = 2; 54b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgstatic const unsigned int ALSA_PLAYOUT_LATENCY = 40*1000; // in us 55b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgstatic const unsigned int ALSA_CAPTURE_FREQ = 48000; 56b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgstatic const unsigned int ALSA_CAPTURE_CH = 2; 57b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgstatic const unsigned int ALSA_CAPTURE_LATENCY = 40*1000; // in us 58b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgstatic const unsigned int ALSA_CAPTURE_WAIT_TIMEOUT = 5; // in ms 59b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 60b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#define FUNC_GET_NUM_OF_DEVICE 0 61b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#define FUNC_GET_DEVICE_NAME 1 62b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#define FUNC_GET_DEVICE_NAME_FOR_AN_ENUM 2 63b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 6464a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgAudioDeviceLinuxALSA::AudioDeviceLinuxALSA(const int32_t id) : 65b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _ptrAudioBuffer(NULL), 66b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _critSect(*CriticalSectionWrapper::CreateCriticalSection()), 67b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _ptrThreadRec(NULL), 68b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _ptrThreadPlay(NULL), 69b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _recThreadID(0), 70b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _playThreadID(0), 71b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _id(id), 72b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _mixerManager(id), 73b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _inputDeviceIndex(0), 74b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _outputDeviceIndex(0), 75b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _inputDeviceIsSpecified(false), 76b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _outputDeviceIsSpecified(false), 77b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _handleRecord(NULL), 78b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _handlePlayout(NULL), 79b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _recordingBuffersizeInFrame(0), 80b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _recordingPeriodSizeInFrame(0), 81b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _playoutBufferSizeInFrame(0), 82b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _playoutPeriodSizeInFrame(0), 83b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _recordingBufferSizeIn10MS(0), 84b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _playoutBufferSizeIn10MS(0), 85b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _recordingFramesIn10MS(0), 86b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _playoutFramesIn10MS(0), 87b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _recordingFreq(ALSA_CAPTURE_FREQ), 88b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _playoutFreq(ALSA_PLAYOUT_FREQ), 89b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _recChannels(ALSA_CAPTURE_CH), 90b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _playChannels(ALSA_PLAYOUT_CH), 91b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _recordingBuffer(NULL), 92b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _playoutBuffer(NULL), 93b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _recordingFramesLeft(0), 94b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _playoutFramesLeft(0), 95b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _playBufType(AudioDeviceModule::kFixedBufferSize), 96b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _initialized(false), 97b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _recording(false), 98b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _playing(false), 99b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _recIsInitialized(false), 100b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _playIsInitialized(false), 101b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _AGC(false), 102b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _recordingDelay(0), 103b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _playoutDelay(0), 104b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _playWarning(0), 105b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _playError(0), 106b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _recWarning(0), 107b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _recError(0), 108b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _playBufDelay(80), 109b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _playBufDelayFixed(80) 110b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 11132b4e2f2d38cb8fe7ca95ea0ab65ba4769ffa230niklas.enbom@webrtc.org memset(_oldKeyState, 0, sizeof(_oldKeyState)); 112b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, id, 113b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org "%s created", __FUNCTION__); 114b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 115b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 116b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 117b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// AudioDeviceLinuxALSA - dtor 118b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 119b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 120b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgAudioDeviceLinuxALSA::~AudioDeviceLinuxALSA() 121b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 122b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, _id, 123b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org "%s destroyed", __FUNCTION__); 1249e035d2ce2a35ae6db3ac47131821056cda31eaewu@webrtc.org 125b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org Terminate(); 126b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 127b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Clean up the recording buffer and playout buffer. 128b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_recordingBuffer) 129b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 130b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org delete [] _recordingBuffer; 131b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _recordingBuffer = NULL; 132b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 133b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_playoutBuffer) 134b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 135b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org delete [] _playoutBuffer; 136b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _playoutBuffer = NULL; 137b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 138b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org delete &_critSect; 139b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 140b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 141b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgvoid AudioDeviceLinuxALSA::AttachAudioBuffer(AudioDeviceBuffer* audioBuffer) 142b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 143b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 144b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org CriticalSectionScoped lock(&_critSect); 145b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 146b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _ptrAudioBuffer = audioBuffer; 147b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 148b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Inform the AudioBuffer about default settings for this implementation. 149b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Set all values to zero here since the actual settings will be done by 150b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // InitPlayout and InitRecording later. 151b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _ptrAudioBuffer->SetRecordingSampleRate(0); 152b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _ptrAudioBuffer->SetPlayoutSampleRate(0); 153b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _ptrAudioBuffer->SetRecordingChannels(0); 154b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _ptrAudioBuffer->SetPlayoutChannels(0); 155b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 156b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 15764a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioDeviceLinuxALSA::ActiveAudioLayer( 158b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org AudioDeviceModule::AudioLayer& audioLayer) const 159b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 160b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org audioLayer = AudioDeviceModule::kLinuxAlsaAudio; 161b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 162b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 163b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 16464a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioDeviceLinuxALSA::Init() 165b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 166b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 167b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org CriticalSectionScoped lock(&_critSect); 168b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 169b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Load libasound 170b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (!AlsaSymbolTable.Load()) 171b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 172b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Alsa is not installed on 173b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // this system 174b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, 175b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org " failed to load symbol table"); 176b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 177b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 178b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 179b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_initialized) 180b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 181b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 182b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 18346b817d939765bef587c575720c18764e3b03fd4fbarchard@google.com#if defined(USE_X11) 18432b4e2f2d38cb8fe7ca95ea0ab65ba4769ffa230niklas.enbom@webrtc.org //Get X display handle for typing detection 18532b4e2f2d38cb8fe7ca95ea0ab65ba4769ffa230niklas.enbom@webrtc.org _XDisplay = XOpenDisplay(NULL); 18632b4e2f2d38cb8fe7ca95ea0ab65ba4769ffa230niklas.enbom@webrtc.org if (!_XDisplay) 18732b4e2f2d38cb8fe7ca95ea0ab65ba4769ffa230niklas.enbom@webrtc.org { 18832b4e2f2d38cb8fe7ca95ea0ab65ba4769ffa230niklas.enbom@webrtc.org WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, 18932b4e2f2d38cb8fe7ca95ea0ab65ba4769ffa230niklas.enbom@webrtc.org " failed to open X display, typing detection will not work"); 19032b4e2f2d38cb8fe7ca95ea0ab65ba4769ffa230niklas.enbom@webrtc.org } 19146b817d939765bef587c575720c18764e3b03fd4fbarchard@google.com#endif 192b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _playWarning = 0; 193b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _playError = 0; 194b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _recWarning = 0; 195b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _recError = 0; 196b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 197b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _initialized = true; 198b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 199b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 200b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 201b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 20264a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioDeviceLinuxALSA::Terminate() 203b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 204b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 205b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (!_initialized) 206b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 207b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 208b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 209b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 210b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org CriticalSectionScoped lock(&_critSect); 211b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 212b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _mixerManager.Close(); 213b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 214b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // RECORDING 215b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_ptrThreadRec) 216b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 217b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org ThreadWrapper* tmpThread = _ptrThreadRec; 218b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _ptrThreadRec = NULL; 219b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _critSect.Leave(); 220b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 221b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org tmpThread->SetNotAlive(); 222b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 223b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (tmpThread->Stop()) 224b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 225b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org delete tmpThread; 226b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 227b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org else 228b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 229b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, 230b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org " failed to close down the rec audio thread"); 231b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 232b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 233b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _critSect.Enter(); 234b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 235b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 236b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // PLAYOUT 237b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_ptrThreadPlay) 238b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 239b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org ThreadWrapper* tmpThread = _ptrThreadPlay; 240b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _ptrThreadPlay = NULL; 241b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _critSect.Leave(); 242b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 243b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org tmpThread->SetNotAlive(); 244b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 245b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (tmpThread->Stop()) 246b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 247b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org delete tmpThread; 248b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 249b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org else 250b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 251b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, 252b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org " failed to close down the play audio thread"); 253b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 254b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 255b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _critSect.Enter(); 256b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 25746b817d939765bef587c575720c18764e3b03fd4fbarchard@google.com#if defined(USE_X11) 25832b4e2f2d38cb8fe7ca95ea0ab65ba4769ffa230niklas.enbom@webrtc.org if (_XDisplay) 25932b4e2f2d38cb8fe7ca95ea0ab65ba4769ffa230niklas.enbom@webrtc.org { 26032b4e2f2d38cb8fe7ca95ea0ab65ba4769ffa230niklas.enbom@webrtc.org XCloseDisplay(_XDisplay); 26132b4e2f2d38cb8fe7ca95ea0ab65ba4769ffa230niklas.enbom@webrtc.org _XDisplay = NULL; 26232b4e2f2d38cb8fe7ca95ea0ab65ba4769ffa230niklas.enbom@webrtc.org } 26346b817d939765bef587c575720c18764e3b03fd4fbarchard@google.com#endif 264b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _initialized = false; 265b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _outputDeviceIsSpecified = false; 266b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _inputDeviceIsSpecified = false; 267b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 268b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 269b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 270b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 271b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgbool AudioDeviceLinuxALSA::Initialized() const 272b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 273b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return (_initialized); 274b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 275b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 27664a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioDeviceLinuxALSA::InitSpeaker() 277b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 278b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 279b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org CriticalSectionScoped lock(&_critSect); 280b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 281b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_playing) 282b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 283b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 284b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 285b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 286b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org char devName[kAdmMaxDeviceNameSize] = {0}; 287b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org GetDevicesInfo(2, true, _outputDeviceIndex, devName, kAdmMaxDeviceNameSize); 288b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return _mixerManager.OpenSpeaker(devName); 289b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 290b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 29164a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioDeviceLinuxALSA::InitMicrophone() 292b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 293b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 294b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org CriticalSectionScoped lock(&_critSect); 295b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 296b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_recording) 297b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 298b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 299b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 300b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 301b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org char devName[kAdmMaxDeviceNameSize] = {0}; 302b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org GetDevicesInfo(2, false, _inputDeviceIndex, devName, kAdmMaxDeviceNameSize); 303b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return _mixerManager.OpenMicrophone(devName); 304b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 305b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 306b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgbool AudioDeviceLinuxALSA::SpeakerIsInitialized() const 307b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 308b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return (_mixerManager.SpeakerIsInitialized()); 309b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 310b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 311b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgbool AudioDeviceLinuxALSA::MicrophoneIsInitialized() const 312b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 313b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return (_mixerManager.MicrophoneIsInitialized()); 314b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 315b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 31664a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioDeviceLinuxALSA::SpeakerVolumeIsAvailable(bool& available) 317b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 318b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 319b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org bool wasInitialized = _mixerManager.SpeakerIsInitialized(); 320b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 321b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Make an attempt to open up the 322b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // output mixer corresponding to the currently selected output device. 323b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (!wasInitialized && InitSpeaker() == -1) 324b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 325b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // If we end up here it means that the selected speaker has no volume 326b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // control. 327b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org available = false; 328b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 329b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 330b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 331b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Given that InitSpeaker was successful, we know that a volume control 332b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // exists 333b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org available = true; 334b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 335b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Close the initialized output mixer 336b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (!wasInitialized) 337b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 338b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _mixerManager.CloseSpeaker(); 339b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 340b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 341b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 342b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 343b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 34464a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioDeviceLinuxALSA::SetSpeakerVolume(uint32_t volume) 345b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 346b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 347b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return (_mixerManager.SetSpeakerVolume(volume)); 348b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 349b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 35064a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioDeviceLinuxALSA::SpeakerVolume(uint32_t& volume) const 351b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 352b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 35364a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.org uint32_t level(0); 354b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 355b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_mixerManager.SpeakerVolume(level) == -1) 356b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 357b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 358b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 359b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 360b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org volume = level; 3619e035d2ce2a35ae6db3ac47131821056cda31eaewu@webrtc.org 362b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 363b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 364b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 365b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 36664a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioDeviceLinuxALSA::SetWaveOutVolume(uint16_t volumeLeft, 36764a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.org uint16_t volumeRight) 368b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 369b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 370b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, 371b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org " API call not supported on this platform"); 372b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 373b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 374b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 37564a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioDeviceLinuxALSA::WaveOutVolume( 37664a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.org uint16_t& /*volumeLeft*/, 37764a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.org uint16_t& /*volumeRight*/) const 378b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 379b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 380b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, 381b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org " API call not supported on this platform"); 382b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 383b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 384b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 38564a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioDeviceLinuxALSA::MaxSpeakerVolume( 38664a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.org uint32_t& maxVolume) const 387b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 388b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 38964a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.org uint32_t maxVol(0); 390b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 391b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_mixerManager.MaxSpeakerVolume(maxVol) == -1) 392b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 393b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 394b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 395b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 396b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org maxVolume = maxVol; 3979e035d2ce2a35ae6db3ac47131821056cda31eaewu@webrtc.org 398b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 399b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 400b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 40164a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioDeviceLinuxALSA::MinSpeakerVolume( 40264a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.org uint32_t& minVolume) const 403b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 404b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 40564a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.org uint32_t minVol(0); 406b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 407b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_mixerManager.MinSpeakerVolume(minVol) == -1) 408b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 409b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 410b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 411b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 412b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org minVolume = minVol; 4139e035d2ce2a35ae6db3ac47131821056cda31eaewu@webrtc.org 414b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 415b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 416b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 41764a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioDeviceLinuxALSA::SpeakerVolumeStepSize( 41864a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.org uint16_t& stepSize) const 419b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 420b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 4219e035d2ce2a35ae6db3ac47131821056cda31eaewu@webrtc.org uint16_t delta(0); 4229e035d2ce2a35ae6db3ac47131821056cda31eaewu@webrtc.org 423b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_mixerManager.SpeakerVolumeStepSize(delta) == -1) 424b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 425b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 426b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 427b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 428b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org stepSize = delta; 429b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 430b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 431b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 432b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 43364a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioDeviceLinuxALSA::SpeakerMuteIsAvailable(bool& available) 434b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 435b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 436b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org bool isAvailable(false); 437b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org bool wasInitialized = _mixerManager.SpeakerIsInitialized(); 438b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 439b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Make an attempt to open up the 440b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // output mixer corresponding to the currently selected output device. 441b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // 442b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (!wasInitialized && InitSpeaker() == -1) 443b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 444b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // If we end up here it means that the selected speaker has no volume 445b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // control, hence it is safe to state that there is no mute control 446b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // already at this stage. 447b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org available = false; 448b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 449b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 450b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 451b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Check if the selected speaker has a mute control 452b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _mixerManager.SpeakerMuteIsAvailable(isAvailable); 453b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 454b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org available = isAvailable; 455b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 456b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Close the initialized output mixer 457b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (!wasInitialized) 458b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 459b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _mixerManager.CloseSpeaker(); 460b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 461b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 462b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 463b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 464b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 46564a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioDeviceLinuxALSA::SetSpeakerMute(bool enable) 466b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 467b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return (_mixerManager.SetSpeakerMute(enable)); 468b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 469b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 47064a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioDeviceLinuxALSA::SpeakerMute(bool& enabled) const 471b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 472b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 4739e035d2ce2a35ae6db3ac47131821056cda31eaewu@webrtc.org bool muted(0); 4749e035d2ce2a35ae6db3ac47131821056cda31eaewu@webrtc.org 475b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_mixerManager.SpeakerMute(muted) == -1) 476b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 477b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 478b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 479b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 480b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org enabled = muted; 4819e035d2ce2a35ae6db3ac47131821056cda31eaewu@webrtc.org 482b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 483b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 484b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 48564a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioDeviceLinuxALSA::MicrophoneMuteIsAvailable(bool& available) 486b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 487b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 488b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org bool isAvailable(false); 489b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org bool wasInitialized = _mixerManager.MicrophoneIsInitialized(); 490b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 491b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Make an attempt to open up the 492b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // input mixer corresponding to the currently selected input device. 493b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // 494b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (!wasInitialized && InitMicrophone() == -1) 495b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 496b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // If we end up here it means that the selected microphone has no volume 497b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // control, hence it is safe to state that there is no mute control 498b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // already at this stage. 499b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org available = false; 500b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 501b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 502b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 503b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Check if the selected microphone has a mute control 504b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // 505b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _mixerManager.MicrophoneMuteIsAvailable(isAvailable); 506b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org available = isAvailable; 507b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 508b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Close the initialized input mixer 509b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // 510b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (!wasInitialized) 511b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 512b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _mixerManager.CloseMicrophone(); 513b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 514b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 515b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 516b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 517b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 51864a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioDeviceLinuxALSA::SetMicrophoneMute(bool enable) 519b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 520b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return (_mixerManager.SetMicrophoneMute(enable)); 521b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 522b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 523b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 524b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// MicrophoneMute 525b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 526b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 52764a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioDeviceLinuxALSA::MicrophoneMute(bool& enabled) const 528b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 529b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 5309e035d2ce2a35ae6db3ac47131821056cda31eaewu@webrtc.org bool muted(0); 5319e035d2ce2a35ae6db3ac47131821056cda31eaewu@webrtc.org 532b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_mixerManager.MicrophoneMute(muted) == -1) 533b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 534b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 535b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 536b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 537b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org enabled = muted; 538b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 539b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 540b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 54164a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioDeviceLinuxALSA::MicrophoneBoostIsAvailable(bool& available) 542b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 5439e035d2ce2a35ae6db3ac47131821056cda31eaewu@webrtc.org 544b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org bool isAvailable(false); 545b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org bool wasInitialized = _mixerManager.MicrophoneIsInitialized(); 546b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 547b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Enumerate all avaliable microphone and make an attempt to open up the 548b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // input mixer corresponding to the currently selected input device. 549b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // 550b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (!wasInitialized && InitMicrophone() == -1) 551b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 552b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // If we end up here it means that the selected microphone has no volume 553b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // control, hence it is safe to state that there is no boost control 554b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // already at this stage. 555b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org available = false; 556b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 557b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 558b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 559b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Check if the selected microphone has a boost control 560b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _mixerManager.MicrophoneBoostIsAvailable(isAvailable); 561b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org available = isAvailable; 562b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 563b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Close the initialized input mixer 564b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (!wasInitialized) 565b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 566b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _mixerManager.CloseMicrophone(); 567b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 568b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 569b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 570b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 571b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 57264a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioDeviceLinuxALSA::SetMicrophoneBoost(bool enable) 573b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 574b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 575b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return (_mixerManager.SetMicrophoneBoost(enable)); 576b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 577b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 57864a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioDeviceLinuxALSA::MicrophoneBoost(bool& enabled) const 579b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 580b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 5819e035d2ce2a35ae6db3ac47131821056cda31eaewu@webrtc.org bool onOff(0); 5829e035d2ce2a35ae6db3ac47131821056cda31eaewu@webrtc.org 583b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_mixerManager.MicrophoneBoost(onOff) == -1) 584b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 585b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 586b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 587b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 588b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org enabled = onOff; 5899e035d2ce2a35ae6db3ac47131821056cda31eaewu@webrtc.org 590b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 591b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 592b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 59364a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioDeviceLinuxALSA::StereoRecordingIsAvailable(bool& available) 594b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 595b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 596b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org CriticalSectionScoped lock(&_critSect); 597b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 598b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // If we already have initialized in stereo it's obviously available 599b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_recIsInitialized && (2 == _recChannels)) 600b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 601b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org available = true; 602b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 603b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 604b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 605b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Save rec states and the number of rec channels 606b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org bool recIsInitialized = _recIsInitialized; 607b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org bool recording = _recording; 608b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org int recChannels = _recChannels; 609b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 610b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org available = false; 6119e035d2ce2a35ae6db3ac47131821056cda31eaewu@webrtc.org 612b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Stop/uninitialize recording if initialized (and possibly started) 613b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_recIsInitialized) 614b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 615b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org StopRecording(); 616b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 617b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 618b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Try init in stereo; 619b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _recChannels = 2; 620b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (InitRecording() == 0) 621b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 622b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org available = true; 623b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 624b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 625b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Stop/uninitialize recording 626b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org StopRecording(); 627b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 628b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Recover previous states 629b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _recChannels = recChannels; 630b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (recIsInitialized) 631b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 632b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org InitRecording(); 633b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 634b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (recording) 635b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 636b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org StartRecording(); 637b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 638b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 639b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 640b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 641b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 64264a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioDeviceLinuxALSA::SetStereoRecording(bool enable) 643b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 644b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 645b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (enable) 646b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _recChannels = 2; 647b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org else 648b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _recChannels = 1; 649b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 650b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 651b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 652b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 65364a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioDeviceLinuxALSA::StereoRecording(bool& enabled) const 654b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 655b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 656b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_recChannels == 2) 657b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org enabled = true; 658b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org else 659b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org enabled = false; 660b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 661b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 662b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 663b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 66464a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioDeviceLinuxALSA::StereoPlayoutIsAvailable(bool& available) 665b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 666b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 667b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org CriticalSectionScoped lock(&_critSect); 668b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 669b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // If we already have initialized in stereo it's obviously available 670b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_playIsInitialized && (2 == _playChannels)) 671b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 672b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org available = true; 673b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 674b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 675b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 676b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Save rec states and the number of rec channels 677b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org bool playIsInitialized = _playIsInitialized; 678b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org bool playing = _playing; 679b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org int playChannels = _playChannels; 680b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 681b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org available = false; 6829e035d2ce2a35ae6db3ac47131821056cda31eaewu@webrtc.org 683b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Stop/uninitialize recording if initialized (and possibly started) 684b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_playIsInitialized) 685b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 686b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org StopPlayout(); 687b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 688b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 689b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Try init in stereo; 690b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _playChannels = 2; 691b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (InitPlayout() == 0) 692b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 693b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org available = true; 694b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 695b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 696b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Stop/uninitialize recording 697b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org StopPlayout(); 698b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 699b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Recover previous states 700b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _playChannels = playChannels; 701b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (playIsInitialized) 702b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 703b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org InitPlayout(); 704b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 705b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (playing) 706b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 707b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org StartPlayout(); 708b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 709b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 710b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 711b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 712b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 71364a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioDeviceLinuxALSA::SetStereoPlayout(bool enable) 714b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 715b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 716b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (enable) 717b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _playChannels = 2; 718b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org else 719b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _playChannels = 1; 720b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 721b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 722b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 723b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 72464a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioDeviceLinuxALSA::StereoPlayout(bool& enabled) const 725b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 726b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 727b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_playChannels == 2) 728b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org enabled = true; 729b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org else 730b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org enabled = false; 731b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 732b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 733b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 734b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 73564a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioDeviceLinuxALSA::SetAGC(bool enable) 736b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 737b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 738b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _AGC = enable; 739b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 740b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 741b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 742b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 743b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgbool AudioDeviceLinuxALSA::AGC() const 744b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 745b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 746b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return _AGC; 747b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 748b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 74964a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioDeviceLinuxALSA::MicrophoneVolumeIsAvailable(bool& available) 750b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 751b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 752b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org bool wasInitialized = _mixerManager.MicrophoneIsInitialized(); 753b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 754b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Make an attempt to open up the 755b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // input mixer corresponding to the currently selected output device. 756b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (!wasInitialized && InitMicrophone() == -1) 757b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 758b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // If we end up here it means that the selected microphone has no volume 759b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // control. 760b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org available = false; 761b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 762b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 763b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 764b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Given that InitMicrophone was successful, we know that a volume control 765b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // exists 766b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org available = true; 767b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 768b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Close the initialized input mixer 769b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (!wasInitialized) 770b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 771b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _mixerManager.CloseMicrophone(); 772b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 773b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 774b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 775b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 776b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 77764a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioDeviceLinuxALSA::SetMicrophoneVolume(uint32_t volume) 778b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 779b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 780b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return (_mixerManager.SetMicrophoneVolume(volume)); 7819e035d2ce2a35ae6db3ac47131821056cda31eaewu@webrtc.org 782b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 783b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 784b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 78564a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioDeviceLinuxALSA::MicrophoneVolume(uint32_t& volume) const 786b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 787b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 78864a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.org uint32_t level(0); 789b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 790b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_mixerManager.MicrophoneVolume(level) == -1) 791b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 792b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, 793b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org " failed to retrive current microphone level"); 794b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 795b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 796b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 797b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org volume = level; 7989e035d2ce2a35ae6db3ac47131821056cda31eaewu@webrtc.org 799b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 800b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 801b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 80264a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioDeviceLinuxALSA::MaxMicrophoneVolume( 80364a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.org uint32_t& maxVolume) const 804b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 805b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 80664a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.org uint32_t maxVol(0); 807b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 808b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_mixerManager.MaxMicrophoneVolume(maxVol) == -1) 809b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 810b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 811b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 812b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 813b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org maxVolume = maxVol; 814b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 815b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 816b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 817b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 81864a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioDeviceLinuxALSA::MinMicrophoneVolume( 81964a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.org uint32_t& minVolume) const 820b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 821b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 82264a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.org uint32_t minVol(0); 823b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 824b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_mixerManager.MinMicrophoneVolume(minVol) == -1) 825b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 826b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 827b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 828b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 829b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org minVolume = minVol; 830b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 831b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 832b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 833b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 83464a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioDeviceLinuxALSA::MicrophoneVolumeStepSize( 83564a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.org uint16_t& stepSize) const 836b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 837b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 8389e035d2ce2a35ae6db3ac47131821056cda31eaewu@webrtc.org uint16_t delta(0); 8399e035d2ce2a35ae6db3ac47131821056cda31eaewu@webrtc.org 840b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_mixerManager.MicrophoneVolumeStepSize(delta) == -1) 841b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 842b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 843b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 844b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 845b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org stepSize = delta; 846b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 847b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 848b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 849b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 85064a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint16_t AudioDeviceLinuxALSA::PlayoutDevices() 851b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 852b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 85364a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.org return (int16_t)GetDevicesInfo(0, true); 854b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 855b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 85664a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioDeviceLinuxALSA::SetPlayoutDevice(uint16_t index) 857b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 858b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 859b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_playIsInitialized) 860b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 861b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 862b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 863b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 86464a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.org uint32_t nDevices = GetDevicesInfo(0, true); 865b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, 866b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org " number of availiable audio output devices is %u", nDevices); 867b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 868b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (index > (nDevices-1)) 869b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 870b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, 871b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org " device index is out of range [0,%u]", (nDevices-1)); 872b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 873b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 874b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 875b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _outputDeviceIndex = index; 876b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _outputDeviceIsSpecified = true; 877b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 878b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 879b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 880b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 88164a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioDeviceLinuxALSA::SetPlayoutDevice( 882b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org AudioDeviceModule::WindowsDeviceType /*device*/) 883b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 884b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, 885b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org "WindowsDeviceType not supported"); 886b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 887b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 888b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 88964a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioDeviceLinuxALSA::PlayoutDeviceName( 89064a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.org uint16_t index, 891b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org char name[kAdmMaxDeviceNameSize], 892b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org char guid[kAdmMaxGuidSize]) 893b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 894b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 89564a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.org const uint16_t nDevices(PlayoutDevices()); 896b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 897b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if ((index > (nDevices-1)) || (name == NULL)) 898b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 899b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 900b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 901b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 902b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org memset(name, 0, kAdmMaxDeviceNameSize); 903b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 904b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (guid != NULL) 905b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 906b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org memset(guid, 0, kAdmMaxGuidSize); 907b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 908b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 909b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return GetDevicesInfo(1, true, index, name, kAdmMaxDeviceNameSize); 910b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 911b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 91264a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioDeviceLinuxALSA::RecordingDeviceName( 91364a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.org uint16_t index, 914b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org char name[kAdmMaxDeviceNameSize], 915b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org char guid[kAdmMaxGuidSize]) 916b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 917b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 91864a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.org const uint16_t nDevices(RecordingDevices()); 919b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 920b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if ((index > (nDevices-1)) || (name == NULL)) 921b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 922b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 923b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 924b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 925b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org memset(name, 0, kAdmMaxDeviceNameSize); 926b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 927b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (guid != NULL) 928b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 929b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org memset(guid, 0, kAdmMaxGuidSize); 930b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 9319e035d2ce2a35ae6db3ac47131821056cda31eaewu@webrtc.org 932b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return GetDevicesInfo(1, false, index, name, kAdmMaxDeviceNameSize); 933b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 934b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 93564a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint16_t AudioDeviceLinuxALSA::RecordingDevices() 936b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 937b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 93864a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.org return (int16_t)GetDevicesInfo(0, false); 939b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 940b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 94164a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioDeviceLinuxALSA::SetRecordingDevice(uint16_t index) 942b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 943b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 944b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_recIsInitialized) 945b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 946b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 947b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 948b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 94964a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.org uint32_t nDevices = GetDevicesInfo(0, false); 950b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, 951b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org " number of availiable audio input devices is %u", nDevices); 952b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 953b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (index > (nDevices-1)) 954b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 955b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, 956b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org " device index is out of range [0,%u]", (nDevices-1)); 957b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 958b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 959b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 960b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _inputDeviceIndex = index; 961b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _inputDeviceIsSpecified = true; 962b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 963b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 964b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 965b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 966b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 967b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// SetRecordingDevice II (II) 968b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 969b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 97064a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioDeviceLinuxALSA::SetRecordingDevice( 971b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org AudioDeviceModule::WindowsDeviceType /*device*/) 972b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 973b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, 974b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org "WindowsDeviceType not supported"); 975b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 976b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 977b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 97864a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioDeviceLinuxALSA::PlayoutIsAvailable(bool& available) 979b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 9809e035d2ce2a35ae6db3ac47131821056cda31eaewu@webrtc.org 981b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org available = false; 982b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 983b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Try to initialize the playout side with mono 984b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Assumes that user set num channels after calling this function 985b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _playChannels = 1; 98664a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.org int32_t res = InitPlayout(); 987b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 988b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Cancel effect of initialization 989b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org StopPlayout(); 990b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 991b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (res != -1) 992b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 993b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org available = true; 994b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 995b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org else 996b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 997b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // It may be possible to play out in stereo 998b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org res = StereoPlayoutIsAvailable(available); 999b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (available) 1000b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1001b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Then set channels to 2 so InitPlayout doesn't fail 1002b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _playChannels = 2; 1003b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1004b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 10059e035d2ce2a35ae6db3ac47131821056cda31eaewu@webrtc.org 1006b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return res; 1007b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 1008b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 100964a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioDeviceLinuxALSA::RecordingIsAvailable(bool& available) 1010b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 10119e035d2ce2a35ae6db3ac47131821056cda31eaewu@webrtc.org 1012b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org available = false; 1013b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1014b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Try to initialize the recording side with mono 1015b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Assumes that user set num channels after calling this function 1016b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _recChannels = 1; 101764a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.org int32_t res = InitRecording(); 1018b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1019b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Cancel effect of initialization 1020b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org StopRecording(); 1021b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1022b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (res != -1) 1023b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1024b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org available = true; 1025b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1026b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org else 1027b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1028b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // It may be possible to record in stereo 1029b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org res = StereoRecordingIsAvailable(available); 1030b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (available) 1031b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1032b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Then set channels to 2 so InitPlayout doesn't fail 1033b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _recChannels = 2; 1034b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1035b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 10369e035d2ce2a35ae6db3ac47131821056cda31eaewu@webrtc.org 1037b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return res; 1038b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 1039b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 104064a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioDeviceLinuxALSA::InitPlayout() 1041b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 1042b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1043b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org int errVal = 0; 1044b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1045b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org CriticalSectionScoped lock(&_critSect); 1046b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_playing) 1047b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1048b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 1049b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1050b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1051b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (!_outputDeviceIsSpecified) 1052b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1053b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 1054b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1055b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1056b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_playIsInitialized) 1057b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1058b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 1059b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1060b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Initialize the speaker (devices might have been added or removed) 1061b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (InitSpeaker() == -1) 1062b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1063b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, 1064b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org " InitSpeaker() failed"); 1065b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1066b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1067b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Start by closing any existing wave-output devices 1068b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // 1069b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_handlePlayout != NULL) 1070b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1071b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org LATE(snd_pcm_close)(_handlePlayout); 1072b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _handlePlayout = NULL; 1073b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _playIsInitialized = false; 1074b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (errVal < 0) 1075b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1076b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, 1077b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org " Error closing current playout sound device, error:" 1078b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org " %s", LATE(snd_strerror)(errVal)); 1079b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1080b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1081b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1082b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Open PCM device for playout 1083b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org char deviceName[kAdmMaxDeviceNameSize] = {0}; 1084b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org GetDevicesInfo(2, true, _outputDeviceIndex, deviceName, 1085b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org kAdmMaxDeviceNameSize); 1086b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1087b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, 1088b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org " InitPlayout open (%s)", deviceName); 1089b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1090b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org errVal = LATE(snd_pcm_open) 1091b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org (&_handlePlayout, 1092b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org deviceName, 1093b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org SND_PCM_STREAM_PLAYBACK, 1094b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org SND_PCM_NONBLOCK); 1095b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1096b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (errVal == -EBUSY) // Device busy - try some more! 1097b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1098b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org for (int i=0; i < 5; i++) 1099b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1100b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org SleepMs(1000); 1101b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org errVal = LATE(snd_pcm_open) 1102b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org (&_handlePlayout, 1103b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org deviceName, 1104b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org SND_PCM_STREAM_PLAYBACK, 1105b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org SND_PCM_NONBLOCK); 1106b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (errVal == 0) 1107b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1108b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org break; 1109b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1110b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1111b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1112b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (errVal < 0) 1113b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1114b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, 1115b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org " unable to open playback device: %s (%d)", 1116b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org LATE(snd_strerror)(errVal), 1117b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org errVal); 1118b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _handlePlayout = NULL; 1119b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 1120b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1121b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1122b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _playoutFramesIn10MS = _playoutFreq/100; 1123b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if ((errVal = LATE(snd_pcm_set_params)( _handlePlayout, 1124d7e904161d5c59c61cbf094b16bca6e79ada713aandrew@webrtc.org#if defined(WEBRTC_ARCH_BIG_ENDIAN) 1125b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org SND_PCM_FORMAT_S16_BE, 1126b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#else 1127b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org SND_PCM_FORMAT_S16_LE, //format 1128b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#endif 1129b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org SND_PCM_ACCESS_RW_INTERLEAVED, //access 1130b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _playChannels, //channels 1131b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _playoutFreq, //rate 1132b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1, //soft_resample 1133b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org ALSA_PLAYOUT_LATENCY //40*1000 //latency required overall latency in us 1134b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org )) < 0) 1135b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { /* 0.5sec */ 1136b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _playoutFramesIn10MS = 0; 1137b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, 1138b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org " unable to set playback device: %s (%d)", 1139b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org LATE(snd_strerror)(errVal), 1140b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org errVal); 1141b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org ErrorRecovery(errVal, _handlePlayout); 1142b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org errVal = LATE(snd_pcm_close)(_handlePlayout); 1143b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _handlePlayout = NULL; 1144b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 1145b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1146b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1147b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org errVal = LATE(snd_pcm_get_params)(_handlePlayout, 1148b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org &_playoutBufferSizeInFrame, &_playoutPeriodSizeInFrame); 1149b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (errVal < 0) 1150b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1151b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, 1152b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org " snd_pcm_get_params %s", 1153b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org LATE(snd_strerror)(errVal), 1154b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org errVal); 1155b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _playoutBufferSizeInFrame = 0; 1156b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _playoutPeriodSizeInFrame = 0; 1157b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1158b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org else { 1159b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, 1160b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org " playout snd_pcm_get_params " 1161b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org "buffer_size:%d period_size :%d", 1162b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _playoutBufferSizeInFrame, _playoutPeriodSizeInFrame); 1163b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1164b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1165b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_ptrAudioBuffer) 1166b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1167b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Update webrtc audio buffer with the selected parameters 1168b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _ptrAudioBuffer->SetPlayoutSampleRate(_playoutFreq); 1169b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _ptrAudioBuffer->SetPlayoutChannels(_playChannels); 1170b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1171b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1172b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Set play buffer size 1173b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _playoutBufferSizeIn10MS = LATE(snd_pcm_frames_to_bytes)( 1174b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _handlePlayout, _playoutFramesIn10MS); 1175b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1176b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Init varaibles used for play 1177b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _playWarning = 0; 1178b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _playError = 0; 1179b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1180b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_handlePlayout != NULL) 1181b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1182b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _playIsInitialized = true; 1183b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 1184b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1185b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org else 1186b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1187b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 1188b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1189b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1190b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 1191b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 1192b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 119364a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioDeviceLinuxALSA::InitRecording() 1194b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 1195b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1196b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org int errVal = 0; 1197b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1198b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org CriticalSectionScoped lock(&_critSect); 1199b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1200b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_recording) 1201b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1202b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 1203b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1204b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1205b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (!_inputDeviceIsSpecified) 1206b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1207b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 1208b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1209b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1210b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_recIsInitialized) 1211b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1212b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 1213b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1214b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1215b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Initialize the microphone (devices might have been added or removed) 1216b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (InitMicrophone() == -1) 1217b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1218b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, 1219b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org " InitMicrophone() failed"); 1220b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1221b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1222b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Start by closing any existing pcm-input devices 1223b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // 1224b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_handleRecord != NULL) 1225b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1226b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org int errVal = LATE(snd_pcm_close)(_handleRecord); 1227b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _handleRecord = NULL; 1228b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _recIsInitialized = false; 1229b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (errVal < 0) 1230b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1231b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, 1232b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org " Error closing current recording sound device," 1233b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org " error: %s", 1234b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org LATE(snd_strerror)(errVal)); 1235b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1236b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1237b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1238b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Open PCM device for recording 1239b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // The corresponding settings for playout are made after the record settings 1240b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org char deviceName[kAdmMaxDeviceNameSize] = {0}; 1241b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org GetDevicesInfo(2, false, _inputDeviceIndex, deviceName, 1242b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org kAdmMaxDeviceNameSize); 1243b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1244b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, 1245b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org "InitRecording open (%s)", deviceName); 1246b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org errVal = LATE(snd_pcm_open) 1247b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org (&_handleRecord, 1248b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org deviceName, 1249b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org SND_PCM_STREAM_CAPTURE, 1250b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org SND_PCM_NONBLOCK); 1251b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1252b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Available modes: 0 = blocking, SND_PCM_NONBLOCK, SND_PCM_ASYNC 1253b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (errVal == -EBUSY) // Device busy - try some more! 1254b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1255b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org for (int i=0; i < 5; i++) 1256b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1257b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org SleepMs(1000); 1258b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org errVal = LATE(snd_pcm_open) 1259b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org (&_handleRecord, 1260b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org deviceName, 1261b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org SND_PCM_STREAM_CAPTURE, 1262b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org SND_PCM_NONBLOCK); 1263b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (errVal == 0) 1264b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1265b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org break; 1266b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1267b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1268b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1269b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (errVal < 0) 1270b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1271b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, 1272b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org " unable to open record device: %s", 1273b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org LATE(snd_strerror)(errVal)); 1274b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _handleRecord = NULL; 1275b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 1276b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1277b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1278b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _recordingFramesIn10MS = _recordingFreq/100; 1279b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if ((errVal = LATE(snd_pcm_set_params)(_handleRecord, 1280d7e904161d5c59c61cbf094b16bca6e79ada713aandrew@webrtc.org#if defined(WEBRTC_ARCH_BIG_ENDIAN) 1281b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org SND_PCM_FORMAT_S16_BE, //format 1282b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#else 1283b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org SND_PCM_FORMAT_S16_LE, //format 1284b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#endif 1285b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org SND_PCM_ACCESS_RW_INTERLEAVED, //access 1286b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _recChannels, //channels 1287b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _recordingFreq, //rate 1288b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1, //soft_resample 1289b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org ALSA_CAPTURE_LATENCY //latency in us 1290b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org )) < 0) 1291b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1292b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Fall back to another mode then. 1293b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_recChannels == 1) 1294b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _recChannels = 2; 1295b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org else 1296b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _recChannels = 1; 1297b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1298b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if ((errVal = LATE(snd_pcm_set_params)(_handleRecord, 1299d7e904161d5c59c61cbf094b16bca6e79ada713aandrew@webrtc.org#if defined(WEBRTC_ARCH_BIG_ENDIAN) 1300b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org SND_PCM_FORMAT_S16_BE, //format 1301b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#else 1302b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org SND_PCM_FORMAT_S16_LE, //format 1303b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#endif 1304b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org SND_PCM_ACCESS_RW_INTERLEAVED, //access 1305b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _recChannels, //channels 1306b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _recordingFreq, //rate 1307b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1, //soft_resample 1308b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org ALSA_CAPTURE_LATENCY //latency in us 1309b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org )) < 0) 1310b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1311b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _recordingFramesIn10MS = 0; 1312b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, 1313b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org " unable to set record settings: %s (%d)", 1314b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org LATE(snd_strerror)(errVal), errVal); 1315b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org ErrorRecovery(errVal, _handleRecord); 1316b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org errVal = LATE(snd_pcm_close)(_handleRecord); 1317b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _handleRecord = NULL; 1318b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 1319b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1320b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1321b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1322b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org errVal = LATE(snd_pcm_get_params)(_handleRecord, 1323b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org &_recordingBuffersizeInFrame, &_recordingPeriodSizeInFrame); 1324b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (errVal < 0) 1325b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1326b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, 1327b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org " snd_pcm_get_params %s", 1328b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org LATE(snd_strerror)(errVal), errVal); 1329b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _recordingBuffersizeInFrame = 0; 1330b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _recordingPeriodSizeInFrame = 0; 1331b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1332b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org else { 1333b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, 1334b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org " capture snd_pcm_get_params " 1335b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org "buffer_size:%d period_size:%d", 1336b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _recordingBuffersizeInFrame, _recordingPeriodSizeInFrame); 1337b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1338b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1339b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_ptrAudioBuffer) 1340b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1341b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Update webrtc audio buffer with the selected parameters 1342b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _ptrAudioBuffer->SetRecordingSampleRate(_recordingFreq); 1343b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _ptrAudioBuffer->SetRecordingChannels(_recChannels); 1344b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1345b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1346b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Set rec buffer size and create buffer 1347b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _recordingBufferSizeIn10MS = LATE(snd_pcm_frames_to_bytes)( 1348b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _handleRecord, _recordingFramesIn10MS); 1349b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1350b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_handleRecord != NULL) 1351b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1352b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Mark recording side as initialized 1353b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _recIsInitialized = true; 1354b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 1355b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1356b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org else 1357b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1358b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 1359b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1360b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1361b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 1362b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 1363b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 136464a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioDeviceLinuxALSA::StartRecording() 1365b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 1366b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1367b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (!_recIsInitialized) 1368b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1369b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 1370b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1371b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1372b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_recording) 1373b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1374b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 1375b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1376b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1377b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _recording = true; 1378b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1379b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org int errVal = 0; 1380b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _recordingFramesLeft = _recordingFramesIn10MS; 1381b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1382b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Make sure we only create the buffer once. 1383b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (!_recordingBuffer) 138464a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.org _recordingBuffer = new int8_t[_recordingBufferSizeIn10MS]; 1385b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (!_recordingBuffer) 1386b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1387b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceCritical, kTraceAudioDevice, _id, 1388b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org " failed to alloc recording buffer"); 1389b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _recording = false; 1390b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 1391b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1392b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // RECORDING 1393b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org const char* threadName = "webrtc_audio_module_capture_thread"; 1394b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _ptrThreadRec = ThreadWrapper::CreateThread(RecThreadFunc, 1395b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org this, 1396b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org kRealtimePriority, 1397b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org threadName); 1398b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_ptrThreadRec == NULL) 1399b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1400b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceCritical, kTraceAudioDevice, _id, 1401b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org " failed to create the rec audio thread"); 1402b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _recording = false; 1403b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org delete [] _recordingBuffer; 1404b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _recordingBuffer = NULL; 1405b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 1406b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1407b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1408b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org unsigned int threadID(0); 1409b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (!_ptrThreadRec->Start(threadID)) 1410b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1411b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceCritical, kTraceAudioDevice, _id, 1412b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org " failed to start the rec audio thread"); 1413b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _recording = false; 1414b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org delete _ptrThreadRec; 1415b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _ptrThreadRec = NULL; 1416b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org delete [] _recordingBuffer; 1417b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _recordingBuffer = NULL; 1418b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 1419b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1420b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _recThreadID = threadID; 1421b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1422b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org errVal = LATE(snd_pcm_prepare)(_handleRecord); 1423b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (errVal < 0) 1424b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1425b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, 1426b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org " capture snd_pcm_prepare failed (%s)\n", 1427b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org LATE(snd_strerror)(errVal)); 1428b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // just log error 1429b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // if snd_pcm_open fails will return -1 1430b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1431b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1432b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org errVal = LATE(snd_pcm_start)(_handleRecord); 1433b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (errVal < 0) 1434b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1435b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, 1436b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org " capture snd_pcm_start err: %s", 1437b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org LATE(snd_strerror)(errVal)); 1438b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org errVal = LATE(snd_pcm_start)(_handleRecord); 1439b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (errVal < 0) 1440b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1441b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, 1442b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org " capture snd_pcm_start 2nd try err: %s", 1443b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org LATE(snd_strerror)(errVal)); 1444b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org StopRecording(); 1445b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 1446b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1447b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1448b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1449b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 1450b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 1451b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 145264a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioDeviceLinuxALSA::StopRecording() 1453b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 1454b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1455b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1456b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org CriticalSectionScoped lock(&_critSect); 1457b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1458b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (!_recIsInitialized) 1459b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1460b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 1461b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1462b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1463b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_handleRecord == NULL) 1464b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1465b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 1466b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1467b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1468b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Make sure we don't start recording (it's asynchronous). 1469b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _recIsInitialized = false; 1470b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _recording = false; 1471b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1472b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1473b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_ptrThreadRec && !_ptrThreadRec->Stop()) 1474b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1475b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, 1476b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org " failed to stop the rec audio thread"); 1477b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 1478b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1479b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org else { 1480b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org delete _ptrThreadRec; 1481b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _ptrThreadRec = NULL; 1482b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1483b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1484b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org CriticalSectionScoped lock(&_critSect); 1485b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _recordingFramesLeft = 0; 1486b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_recordingBuffer) 1487b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1488b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org delete [] _recordingBuffer; 1489b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _recordingBuffer = NULL; 1490b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1491b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1492b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Stop and close pcm recording device. 1493b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org int errVal = LATE(snd_pcm_drop)(_handleRecord); 1494b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (errVal < 0) 1495b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1496b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, 1497b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org " Error stop recording: %s", 1498b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org LATE(snd_strerror)(errVal)); 1499b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 1500b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1501b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1502b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org errVal = LATE(snd_pcm_close)(_handleRecord); 1503b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (errVal < 0) 1504b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1505b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, 1506b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org " Error closing record sound device, error: %s", 1507b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org LATE(snd_strerror)(errVal)); 1508b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 1509b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1510b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1511b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Check if we have muted and unmute if so. 1512b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org bool muteEnabled = false; 1513b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org MicrophoneMute(muteEnabled); 1514b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (muteEnabled) 1515b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1516b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org SetMicrophoneMute(false); 1517b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1518b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1519b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // set the pcm input handle to NULL 1520b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _handleRecord = NULL; 1521b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 1522b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 1523b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1524b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgbool AudioDeviceLinuxALSA::RecordingIsInitialized() const 1525b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 1526b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return (_recIsInitialized); 1527b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 1528b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1529b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgbool AudioDeviceLinuxALSA::Recording() const 1530b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 1531b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return (_recording); 1532b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 1533b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1534b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgbool AudioDeviceLinuxALSA::PlayoutIsInitialized() const 1535b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 1536b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return (_playIsInitialized); 1537b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 1538b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 153964a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioDeviceLinuxALSA::StartPlayout() 1540b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 1541b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (!_playIsInitialized) 1542b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1543b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 1544b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1545b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1546b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_playing) 1547b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1548b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 1549b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1550b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1551b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _playing = true; 1552b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1553b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _playoutFramesLeft = 0; 1554b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (!_playoutBuffer) 155564a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.org _playoutBuffer = new int8_t[_playoutBufferSizeIn10MS]; 1556b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (!_playoutBuffer) 1557b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1558b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, 1559b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org " failed to alloc playout buf"); 1560b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _playing = false; 1561b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 1562b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1563b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1564b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // PLAYOUT 1565b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org const char* threadName = "webrtc_audio_module_play_thread"; 1566b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _ptrThreadPlay = ThreadWrapper::CreateThread(PlayThreadFunc, 1567b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org this, 1568b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org kRealtimePriority, 1569b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org threadName); 1570b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_ptrThreadPlay == NULL) 1571b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1572b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceCritical, kTraceAudioDevice, _id, 1573b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org " failed to create the play audio thread"); 1574b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _playing = false; 1575b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org delete [] _playoutBuffer; 1576b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _playoutBuffer = NULL; 1577b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 1578b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1579b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1580b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org unsigned int threadID(0); 1581b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (!_ptrThreadPlay->Start(threadID)) 1582b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1583b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceCritical, kTraceAudioDevice, _id, 1584b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org " failed to start the play audio thread"); 1585b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _playing = false; 1586b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org delete _ptrThreadPlay; 1587b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _ptrThreadPlay = NULL; 1588b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org delete [] _playoutBuffer; 1589b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _playoutBuffer = NULL; 1590b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 1591b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1592b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _playThreadID = threadID; 1593b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1594b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org int errVal = LATE(snd_pcm_prepare)(_handlePlayout); 1595b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (errVal < 0) 1596b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1597b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceCritical, kTraceAudioDevice, _id, 1598b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org " playout snd_pcm_prepare failed (%s)\n", 1599b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org LATE(snd_strerror)(errVal)); 1600b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // just log error 1601b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // if snd_pcm_open fails will return -1 1602b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1603b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1604b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 1605b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 1606b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 160764a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioDeviceLinuxALSA::StopPlayout() 1608b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 1609b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1610b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1611b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org CriticalSectionScoped lock(&_critSect); 1612b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1613b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (!_playIsInitialized) 1614b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1615b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 1616b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1617b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1618b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_handlePlayout == NULL) 1619b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1620b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 1621b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1622b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1623b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _playing = false; 1624b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1625b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1626b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // stop playout thread first 1627b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_ptrThreadPlay && !_ptrThreadPlay->Stop()) 1628b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1629b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, 1630b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org " failed to stop the play audio thread"); 1631b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 1632b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1633b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org else { 1634b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org delete _ptrThreadPlay; 1635b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _ptrThreadPlay = NULL; 1636b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1637b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1638b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org CriticalSectionScoped lock(&_critSect); 1639b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1640b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _playoutFramesLeft = 0; 1641b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org delete [] _playoutBuffer; 1642b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _playoutBuffer = NULL; 1643b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1644b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // stop and close pcm playout device 1645b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org int errVal = LATE(snd_pcm_drop)(_handlePlayout); 1646b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (errVal < 0) 1647b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1648b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, 1649b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org " Error stop playing: %s", 1650b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org LATE(snd_strerror)(errVal)); 1651b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1652b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1653b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org errVal = LATE(snd_pcm_close)(_handlePlayout); 1654b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (errVal < 0) 1655b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, 1656b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org " Error closing playout sound device, error: %s", 1657b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org LATE(snd_strerror)(errVal)); 1658b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1659b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // set the pcm input handle to NULL 1660b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _playIsInitialized = false; 1661b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _handlePlayout = NULL; 1662b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, 1663b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org " handle_playout is now set to NULL"); 1664b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1665b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 1666b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 1667b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 166864a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioDeviceLinuxALSA::PlayoutDelay(uint16_t& delayMS) const 1669b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 167064a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.org delayMS = (uint16_t)_playoutDelay * 1000 / _playoutFreq; 1671b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 1672b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 1673b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 167464a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioDeviceLinuxALSA::RecordingDelay(uint16_t& delayMS) const 1675b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 1676b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Adding 10ms adjusted value to the record delay due to 10ms buffering. 167764a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.org delayMS = (uint16_t)(10 + _recordingDelay * 1000 / _recordingFreq); 1678b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 1679b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 1680b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1681b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgbool AudioDeviceLinuxALSA::Playing() const 1682b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 1683b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return (_playing); 1684b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 1685b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 1686b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// SetPlayoutBuffer 1687b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 1688b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 168964a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioDeviceLinuxALSA::SetPlayoutBuffer( 1690b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org const AudioDeviceModule::BufferType type, 169164a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.org uint16_t sizeMS) 1692b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 1693b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _playBufType = type; 1694b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (type == AudioDeviceModule::kFixedBufferSize) 1695b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1696b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _playBufDelayFixed = sizeMS; 1697b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1698b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 1699b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 1700b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 170164a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioDeviceLinuxALSA::PlayoutBuffer( 1702b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org AudioDeviceModule::BufferType& type, 170364a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.org uint16_t& sizeMS) const 1704b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 1705b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org type = _playBufType; 1706b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (type == AudioDeviceModule::kFixedBufferSize) 1707b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 17089e035d2ce2a35ae6db3ac47131821056cda31eaewu@webrtc.org sizeMS = _playBufDelayFixed; 1709b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1710b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org else 1711b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 17129e035d2ce2a35ae6db3ac47131821056cda31eaewu@webrtc.org sizeMS = _playBufDelay; 1713b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1714b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1715b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 1716b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 1717b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 171864a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioDeviceLinuxALSA::CPULoad(uint16_t& load) const 1719b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 1720b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1721b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, 1722b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org " API call not supported on this platform"); 1723b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 1724b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 1725b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1726b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgbool AudioDeviceLinuxALSA::PlayoutWarning() const 1727b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 17289e035d2ce2a35ae6db3ac47131821056cda31eaewu@webrtc.org CriticalSectionScoped lock(&_critSect); 1729b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return (_playWarning > 0); 1730b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 1731b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1732b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgbool AudioDeviceLinuxALSA::PlayoutError() const 1733b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 17349e035d2ce2a35ae6db3ac47131821056cda31eaewu@webrtc.org CriticalSectionScoped lock(&_critSect); 1735b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return (_playError > 0); 1736b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 1737b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1738b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgbool AudioDeviceLinuxALSA::RecordingWarning() const 1739b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 17409e035d2ce2a35ae6db3ac47131821056cda31eaewu@webrtc.org CriticalSectionScoped lock(&_critSect); 1741b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return (_recWarning > 0); 1742b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 1743b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1744b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgbool AudioDeviceLinuxALSA::RecordingError() const 1745b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 17469e035d2ce2a35ae6db3ac47131821056cda31eaewu@webrtc.org CriticalSectionScoped lock(&_critSect); 1747b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return (_recError > 0); 1748b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 1749b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1750b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgvoid AudioDeviceLinuxALSA::ClearPlayoutWarning() 1751b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 17529e035d2ce2a35ae6db3ac47131821056cda31eaewu@webrtc.org CriticalSectionScoped lock(&_critSect); 1753b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _playWarning = 0; 1754b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 1755b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1756b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgvoid AudioDeviceLinuxALSA::ClearPlayoutError() 1757b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 17589e035d2ce2a35ae6db3ac47131821056cda31eaewu@webrtc.org CriticalSectionScoped lock(&_critSect); 1759b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _playError = 0; 1760b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 1761b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1762b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgvoid AudioDeviceLinuxALSA::ClearRecordingWarning() 1763b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 17649e035d2ce2a35ae6db3ac47131821056cda31eaewu@webrtc.org CriticalSectionScoped lock(&_critSect); 1765b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _recWarning = 0; 1766b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 1767b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1768b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgvoid AudioDeviceLinuxALSA::ClearRecordingError() 1769b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 17709e035d2ce2a35ae6db3ac47131821056cda31eaewu@webrtc.org CriticalSectionScoped lock(&_critSect); 1771b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _recError = 0; 1772b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 1773b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1774b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ============================================================================ 1775b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// Private Methods 1776b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ============================================================================ 1777b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 177864a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioDeviceLinuxALSA::GetDevicesInfo( 177964a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.org const int32_t function, 1780b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org const bool playback, 178164a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.org const int32_t enumDeviceNo, 1782b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org char* enumDeviceName, 178364a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.org const int32_t ednLen) const 1784b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 17859e035d2ce2a35ae6db3ac47131821056cda31eaewu@webrtc.org 1786b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Device enumeration based on libjingle implementation 1787b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // by Tristan Schmelcher at Google Inc. 1788b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1789b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org const char *type = playback ? "Output" : "Input"; 1790b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // dmix and dsnoop are only for playback and capture, respectively, but ALSA 1791b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // stupidly includes them in both lists. 1792b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org const char *ignorePrefix = playback ? "dsnoop:" : "dmix:" ; 1793b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // (ALSA lists many more "devices" of questionable interest, but we show them 1794b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // just in case the weird devices may actually be desirable for some 1795b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // users/systems.) 1796b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1797b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org int err; 1798b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org int enumCount(0); 1799b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org bool keepSearching(true); 1800b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1801b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // From Chromium issue 95797 1802b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Loop through the sound cards to get Alsa device hints. 1803b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Don't use snd_device_name_hint(-1,..) since there is a access violation 1804b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // inside this ALSA API with libasound.so.2.0.0. 1805b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org int card = -1; 1806b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org while (!(LATE(snd_card_next)(&card)) && (card >= 0) && keepSearching) { 1807b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org void **hints; 1808b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org err = LATE(snd_device_name_hint)(card, "pcm", &hints); 1809b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (err != 0) 1810b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1811b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, 1812b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org "GetDevicesInfo - device name hint error: %s", 1813b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org LATE(snd_strerror)(err)); 1814b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 1815b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1816b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1817b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org enumCount++; // default is 0 1818b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if ((function == FUNC_GET_DEVICE_NAME || 1819b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org function == FUNC_GET_DEVICE_NAME_FOR_AN_ENUM) && enumDeviceNo == 0) 1820b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1821b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org strcpy(enumDeviceName, "default"); 1822b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1823b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org err = LATE(snd_device_name_free_hint)(hints); 1824b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (err != 0) 1825b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1826b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, 1827b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org "GetDevicesInfo - device name free hint error: %s", 1828b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org LATE(snd_strerror)(err)); 1829b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1830b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1831b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 1832b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1833b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1834b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org for (void **list = hints; *list != NULL; ++list) 1835b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1836b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org char *actualType = LATE(snd_device_name_get_hint)(*list, "IOID"); 1837b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (actualType) 1838b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { // NULL means it's both. 1839b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org bool wrongType = (strcmp(actualType, type) != 0); 1840b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org free(actualType); 1841b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (wrongType) 1842b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1843b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Wrong type of device (i.e., input vs. output). 1844b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org continue; 1845b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1846b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1847b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1848b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org char *name = LATE(snd_device_name_get_hint)(*list, "NAME"); 1849b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (!name) 1850b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1851b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, 1852b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org "Device has no name"); 1853b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Skip it. 1854b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org continue; 1855b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1856b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1857b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Now check if we actually want to show this device. 1858b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (strcmp(name, "default") != 0 && 1859b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org strcmp(name, "null") != 0 && 1860b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org strcmp(name, "pulse") != 0 && 1861b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org strncmp(name, ignorePrefix, strlen(ignorePrefix)) != 0) 1862b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1863b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Yes, we do. 1864b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org char *desc = LATE(snd_device_name_get_hint)(*list, "DESC"); 1865b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (!desc) 1866b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1867b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Virtual devices don't necessarily have descriptions. 1868b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Use their names instead. 1869b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org desc = name; 1870b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1871b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1872b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (FUNC_GET_NUM_OF_DEVICE == function) 1873b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1874b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, 1875b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org " Enum device %d - %s", enumCount, name); 1876b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1877b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1878b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if ((FUNC_GET_DEVICE_NAME == function) && 1879b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org (enumDeviceNo == enumCount)) 1880b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1881b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // We have found the enum device, copy the name to buffer. 1882b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org strncpy(enumDeviceName, desc, ednLen); 1883b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org enumDeviceName[ednLen-1] = '\0'; 1884b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org keepSearching = false; 1885b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Replace '\n' with '-'. 1886b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org char * pret = strchr(enumDeviceName, '\n'/*0xa*/); //LF 1887b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (pret) 1888b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *pret = '-'; 1889b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1890b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if ((FUNC_GET_DEVICE_NAME_FOR_AN_ENUM == function) && 1891b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org (enumDeviceNo == enumCount)) 1892b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1893b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // We have found the enum device, copy the name to buffer. 1894b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org strncpy(enumDeviceName, name, ednLen); 1895b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org enumDeviceName[ednLen-1] = '\0'; 1896b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org keepSearching = false; 1897b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1898b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1899b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (keepSearching) 1900b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org ++enumCount; 1901b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1902b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (desc != name) 1903b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org free(desc); 1904b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1905b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1906b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org free(name); 1907b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1908b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (!keepSearching) 1909b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org break; 1910b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1911b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1912b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org err = LATE(snd_device_name_free_hint)(hints); 1913b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (err != 0) 1914b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1915b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, 1916b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org "GetDevicesInfo - device name free hint error: %s", 1917b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org LATE(snd_strerror)(err)); 1918b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Continue and return true anyway, since we did get the whole list. 1919b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1920b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1921b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1922b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (FUNC_GET_NUM_OF_DEVICE == function) 1923b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1924b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (enumCount == 1) // only default? 1925b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org enumCount = 0; 1926b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return enumCount; // Normal return point for function 0 1927b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1928b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1929b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (keepSearching) 1930b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1931b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // If we get here for function 1 and 2, we didn't find the specified 1932b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // enum device. 1933b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, 1934b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org "GetDevicesInfo - Could not find device name or numbers"); 1935b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 1936b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1937b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1938b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 1939b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 1940b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 194164a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioDeviceLinuxALSA::InputSanityCheckAfterUnlockedPeriod() const 1942b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 1943b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_handleRecord == NULL) 1944b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1945b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, 1946b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org " input state has been modified during unlocked period"); 1947b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 1948b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1949b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 1950b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 1951b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 195264a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioDeviceLinuxALSA::OutputSanityCheckAfterUnlockedPeriod() const 1953b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 1954b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_handlePlayout == NULL) 1955b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1956b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, 1957b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org " output state has been modified during unlocked period"); 1958b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 1959b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1960b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 1961b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 1962b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 196364a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioDeviceLinuxALSA::ErrorRecovery(int32_t error, 196464a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.org snd_pcm_t* deviceHandle) 1965b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 1966b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org int st = LATE(snd_pcm_state)(deviceHandle); 1967b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, 1968b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org "Trying to recover from error: %s (%d) (state %d)", 1969b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org (LATE(snd_pcm_stream)(deviceHandle) == SND_PCM_STREAM_CAPTURE) ? 1970b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org "capture" : "playout", LATE(snd_strerror)(error), error, st); 1971b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1972b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // It is recommended to use snd_pcm_recover for all errors. If that function 1973b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // cannot handle the error, the input error code will be returned, otherwise 1974b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // 0 is returned. From snd_pcm_recover API doc: "This functions handles 1975b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // -EINTR (4) (interrupted system call), -EPIPE (32) (playout overrun or 1976b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // capture underrun) and -ESTRPIPE (86) (stream is suspended) error codes 1977b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // trying to prepare given stream for next I/O." 1978b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1979b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org /** Open */ 1980b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // SND_PCM_STATE_OPEN = 0, 1981b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org /** Setup installed */ 1982b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // SND_PCM_STATE_SETUP, 1983b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org /** Ready to start */ 1984b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // SND_PCM_STATE_PREPARED, 1985b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org /** Running */ 1986b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // SND_PCM_STATE_RUNNING, 1987b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org /** Stopped: underrun (playback) or overrun (capture) detected */ 1988b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // SND_PCM_STATE_XRUN,= 4 1989b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org /** Draining: running (playback) or stopped (capture) */ 1990b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // SND_PCM_STATE_DRAINING, 1991b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org /** Paused */ 1992b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // SND_PCM_STATE_PAUSED, 1993b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org /** Hardware is suspended */ 1994b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // SND_PCM_STATE_SUSPENDED, 1995b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // ** Hardware is disconnected */ 1996b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // SND_PCM_STATE_DISCONNECTED, 1997b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // SND_PCM_STATE_LAST = SND_PCM_STATE_DISCONNECTED 1998b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1999b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // snd_pcm_recover isn't available in older alsa, e.g. on the FC4 machine 2000b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // in Sthlm lab. 2001b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2002b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org int res = LATE(snd_pcm_recover)(deviceHandle, error, 1); 2003b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (0 == res) 2004b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 2005b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, 2006b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org " Recovery - snd_pcm_recover OK"); 2007b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2008b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if ((error == -EPIPE || error == -ESTRPIPE) && // Buf underrun/overrun. 2009b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _recording && 2010b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org LATE(snd_pcm_stream)(deviceHandle) == SND_PCM_STREAM_CAPTURE) 2011b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 2012b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // For capture streams we also have to repeat the explicit start() 2013b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // to get data flowing again. 2014b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org int err = LATE(snd_pcm_start)(deviceHandle); 2015b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (err != 0) 2016b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 2017b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, 2018b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org " Recovery - snd_pcm_start error: %u", err); 2019b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 2020b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 2021b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 2022b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2023b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if ((error == -EPIPE || error == -ESTRPIPE) && // Buf underrun/overrun. 2024b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _playing && 2025b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org LATE(snd_pcm_stream)(deviceHandle) == SND_PCM_STREAM_PLAYBACK) 2026b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 2027b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // For capture streams we also have to repeat the explicit start() to get 2028b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // data flowing again. 2029b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org int err = LATE(snd_pcm_start)(deviceHandle); 2030b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (err != 0) 2031b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 2032b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, 2033b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org " Recovery - snd_pcm_start error: %s", 2034b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org LATE(snd_strerror)(err)); 2035b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 2036b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 2037b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 2038b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2039b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -EPIPE == error ? 1 : 0; 2040b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 2041b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org else { 2042b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, 2043b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org " Unrecoverable alsa stream error: %d", res); 2044b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 2045b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2046b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return res; 2047b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 2048b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2049b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ============================================================================ 2050b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// Thread Methods 2051b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ============================================================================ 2052b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2053b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgbool AudioDeviceLinuxALSA::PlayThreadFunc(void* pThis) 2054b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 2055b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return (static_cast<AudioDeviceLinuxALSA*>(pThis)->PlayThreadProcess()); 2056b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 2057b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2058b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgbool AudioDeviceLinuxALSA::RecThreadFunc(void* pThis) 2059b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 2060b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return (static_cast<AudioDeviceLinuxALSA*>(pThis)->RecThreadProcess()); 2061b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 2062b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2063b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgbool AudioDeviceLinuxALSA::PlayThreadProcess() 2064b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 2065b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if(!_playing) 2066b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return false; 2067b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2068b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org int err; 2069b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org snd_pcm_sframes_t frames; 2070b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org snd_pcm_sframes_t avail_frames; 2071b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2072b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org Lock(); 2073b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org //return a positive number of frames ready otherwise a negative error code 2074b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org avail_frames = LATE(snd_pcm_avail_update)(_handlePlayout); 2075b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (avail_frames < 0) 2076b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 2077b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, 2078b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org "playout snd_pcm_avail_update error: %s", 2079b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org LATE(snd_strerror)(avail_frames)); 2080b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org ErrorRecovery(avail_frames, _handlePlayout); 2081b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org UnLock(); 2082b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return true; 2083b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 2084b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org else if (avail_frames == 0) 2085b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 2086b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org UnLock(); 2087b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2088b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org //maximum tixe in milliseconds to wait, a negative value means infinity 2089b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org err = LATE(snd_pcm_wait)(_handlePlayout, 2); 2090b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (err == 0) 2091b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { //timeout occured 2092b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceStream, kTraceAudioDevice, _id, 2093b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org "playout snd_pcm_wait timeout"); 2094b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 2095b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2096b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return true; 2097b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 2098b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2099b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_playoutFramesLeft <= 0) 2100b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 2101b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org UnLock(); 2102b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _ptrAudioBuffer->RequestPlayoutData(_playoutFramesIn10MS); 2103b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org Lock(); 2104b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2105b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _playoutFramesLeft = _ptrAudioBuffer->GetPlayoutData(_playoutBuffer); 2106b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org assert(_playoutFramesLeft == _playoutFramesIn10MS); 2107b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 2108b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 210964a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.org if (static_cast<uint32_t>(avail_frames) > _playoutFramesLeft) 2110b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org avail_frames = _playoutFramesLeft; 2111b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2112b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org int size = LATE(snd_pcm_frames_to_bytes)(_handlePlayout, 2113b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _playoutFramesLeft); 2114b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org frames = LATE(snd_pcm_writei)( 2115b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _handlePlayout, 2116b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org &_playoutBuffer[_playoutBufferSizeIn10MS - size], 2117b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org avail_frames); 2118b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2119b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (frames < 0) 2120b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 2121b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceStream, kTraceAudioDevice, _id, 2122b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org "playout snd_pcm_writei error: %s", 2123b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org LATE(snd_strerror)(frames)); 2124b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _playoutFramesLeft = 0; 2125b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org ErrorRecovery(frames, _handlePlayout); 2126b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org UnLock(); 2127b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return true; 2128b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 2129b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org else { 2130b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org assert(frames==avail_frames); 2131b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _playoutFramesLeft -= frames; 2132b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 2133b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2134b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org UnLock(); 2135b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return true; 2136b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 2137b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2138b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgbool AudioDeviceLinuxALSA::RecThreadProcess() 2139b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 2140b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (!_recording) 2141b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return false; 2142b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2143b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org int err; 2144b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org snd_pcm_sframes_t frames; 2145b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org snd_pcm_sframes_t avail_frames; 214664a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.org int8_t buffer[_recordingBufferSizeIn10MS]; 2147b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2148b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org Lock(); 2149b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2150b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org //return a positive number of frames ready otherwise a negative error code 2151b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org avail_frames = LATE(snd_pcm_avail_update)(_handleRecord); 2152b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (avail_frames < 0) 2153b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 2154b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, 2155b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org "capture snd_pcm_avail_update error: %s", 2156b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org LATE(snd_strerror)(avail_frames)); 2157b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org ErrorRecovery(avail_frames, _handleRecord); 2158b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org UnLock(); 2159b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return true; 2160b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 2161b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org else if (avail_frames == 0) 2162b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { // no frame is available now 2163b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org UnLock(); 2164b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2165b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org //maximum time in milliseconds to wait, a negative value means infinity 2166b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org err = LATE(snd_pcm_wait)(_handleRecord, 2167b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org ALSA_CAPTURE_WAIT_TIMEOUT); 2168b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (err == 0) //timeout occured 2169b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceStream, kTraceAudioDevice, _id, 2170b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org "capture snd_pcm_wait timeout"); 2171b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2172b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return true; 2173b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 2174b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 217564a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.org if (static_cast<uint32_t>(avail_frames) > _recordingFramesLeft) 2176b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org avail_frames = _recordingFramesLeft; 2177b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2178b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org frames = LATE(snd_pcm_readi)(_handleRecord, 2179b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org buffer, avail_frames); // frames to be written 2180b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (frames < 0) 2181b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 2182b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, 2183b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org "capture snd_pcm_readi error: %s", 2184b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org LATE(snd_strerror)(frames)); 2185b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org ErrorRecovery(frames, _handleRecord); 2186b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org UnLock(); 2187b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return true; 2188b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 2189b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org else if (frames > 0) 2190b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 2191b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org assert(frames == avail_frames); 2192b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2193b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org int left_size = LATE(snd_pcm_frames_to_bytes)(_handleRecord, 2194b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _recordingFramesLeft); 2195b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org int size = LATE(snd_pcm_frames_to_bytes)(_handleRecord, frames); 2196b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2197b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org memcpy(&_recordingBuffer[_recordingBufferSizeIn10MS - left_size], 2198b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org buffer, size); 2199b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _recordingFramesLeft -= frames; 2200b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2201b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (!_recordingFramesLeft) 2202b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { // buf is full 2203b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _recordingFramesLeft = _recordingFramesIn10MS; 2204b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2205b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // store the recorded buffer (no action will be taken if the 2206b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // #recorded samples is not a full buffer) 2207b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _ptrAudioBuffer->SetRecordedBuffer(_recordingBuffer, 2208b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _recordingFramesIn10MS); 2209b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 221064a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.org uint32_t currentMicLevel = 0; 221164a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.org uint32_t newMicLevel = 0; 2212b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2213b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (AGC()) 2214b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 2215b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // store current mic level in the audio buffer if AGC is enabled 2216b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (MicrophoneVolume(currentMicLevel) == 0) 2217b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 2218b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (currentMicLevel == 0xffffffff) 2219b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org currentMicLevel = 100; 2220b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // this call does not affect the actual microphone volume 2221b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _ptrAudioBuffer->SetCurrentMicLevel(currentMicLevel); 2222b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 2223b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 2224b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2225b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // calculate delay 2226b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _playoutDelay = 0; 2227b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _recordingDelay = 0; 2228b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_handlePlayout) 2229b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 2230b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org err = LATE(snd_pcm_delay)(_handlePlayout, 2231b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org &_playoutDelay); // returned delay in frames 2232b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (err < 0) 2233b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 2234b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // TODO(xians): Shall we call ErrorRecovery() here? 2235b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _playoutDelay = 0; 2236b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, 2237b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org "playout snd_pcm_delay: %s", 2238b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org LATE(snd_strerror)(err)); 2239b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 2240b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 2241b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2242b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org err = LATE(snd_pcm_delay)(_handleRecord, 2243b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org &_recordingDelay); // returned delay in frames 2244b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (err < 0) 2245b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 2246b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // TODO(xians): Shall we call ErrorRecovery() here? 2247b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _recordingDelay = 0; 2248b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, 2249b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org "capture snd_pcm_delay: %s", 2250b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org LATE(snd_strerror)(err)); 2251b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 2252b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2253b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // TODO(xians): Shall we add 10ms buffer delay to the record delay? 2254b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _ptrAudioBuffer->SetVQEData( 2255b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _playoutDelay * 1000 / _playoutFreq, 2256b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _recordingDelay * 1000 / _recordingFreq, 0); 2257b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 225832b4e2f2d38cb8fe7ca95ea0ab65ba4769ffa230niklas.enbom@webrtc.org _ptrAudioBuffer->SetTypingStatus(KeyPressed()); 225932b4e2f2d38cb8fe7ca95ea0ab65ba4769ffa230niklas.enbom@webrtc.org 2260b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Deliver recorded samples at specified sample rate, mic level etc. 2261b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // to the observer using callback. 2262b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org UnLock(); 2263b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _ptrAudioBuffer->DeliverRecordedData(); 2264b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org Lock(); 2265b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2266b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (AGC()) 2267b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 2268b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org newMicLevel = _ptrAudioBuffer->NewMicLevel(); 2269b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (newMicLevel != 0) 2270b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 2271b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // The VQE will only deliver non-zero microphone levels when a 2272b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // change is needed. Set this new mic level (received from the 2273b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // observer as return value in the callback). 2274b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (SetMicrophoneVolume(newMicLevel) == -1) 2275b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, 2276b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org " the required modification of the " 2277b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org "microphone volume failed"); 2278b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 2279b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 2280b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 2281b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 2282b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2283b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org UnLock(); 2284b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return true; 2285b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 2286b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 228732b4e2f2d38cb8fe7ca95ea0ab65ba4769ffa230niklas.enbom@webrtc.org 228832b4e2f2d38cb8fe7ca95ea0ab65ba4769ffa230niklas.enbom@webrtc.orgbool AudioDeviceLinuxALSA::KeyPressed() const{ 228946b817d939765bef587c575720c18764e3b03fd4fbarchard@google.com#if defined(USE_X11) 229032b4e2f2d38cb8fe7ca95ea0ab65ba4769ffa230niklas.enbom@webrtc.org char szKey[32]; 229132b4e2f2d38cb8fe7ca95ea0ab65ba4769ffa230niklas.enbom@webrtc.org unsigned int i = 0; 229232b4e2f2d38cb8fe7ca95ea0ab65ba4769ffa230niklas.enbom@webrtc.org char state = 0; 229332b4e2f2d38cb8fe7ca95ea0ab65ba4769ffa230niklas.enbom@webrtc.org 229432b4e2f2d38cb8fe7ca95ea0ab65ba4769ffa230niklas.enbom@webrtc.org if (!_XDisplay) 229532b4e2f2d38cb8fe7ca95ea0ab65ba4769ffa230niklas.enbom@webrtc.org return false; 229632b4e2f2d38cb8fe7ca95ea0ab65ba4769ffa230niklas.enbom@webrtc.org 229732b4e2f2d38cb8fe7ca95ea0ab65ba4769ffa230niklas.enbom@webrtc.org // Check key map status 229832b4e2f2d38cb8fe7ca95ea0ab65ba4769ffa230niklas.enbom@webrtc.org XQueryKeymap(_XDisplay, szKey); 229932b4e2f2d38cb8fe7ca95ea0ab65ba4769ffa230niklas.enbom@webrtc.org 230032b4e2f2d38cb8fe7ca95ea0ab65ba4769ffa230niklas.enbom@webrtc.org // A bit change in keymap means a key is pressed 230132b4e2f2d38cb8fe7ca95ea0ab65ba4769ffa230niklas.enbom@webrtc.org for (i = 0; i < sizeof(szKey); i++) 230232b4e2f2d38cb8fe7ca95ea0ab65ba4769ffa230niklas.enbom@webrtc.org state |= (szKey[i] ^ _oldKeyState[i]) & szKey[i]; 230332b4e2f2d38cb8fe7ca95ea0ab65ba4769ffa230niklas.enbom@webrtc.org 230432b4e2f2d38cb8fe7ca95ea0ab65ba4769ffa230niklas.enbom@webrtc.org // Save old state 230532b4e2f2d38cb8fe7ca95ea0ab65ba4769ffa230niklas.enbom@webrtc.org memcpy((char*)_oldKeyState, (char*)szKey, sizeof(_oldKeyState)); 230632b4e2f2d38cb8fe7ca95ea0ab65ba4769ffa230niklas.enbom@webrtc.org return (state != 0); 230746b817d939765bef587c575720c18764e3b03fd4fbarchard@google.com#else 230846b817d939765bef587c575720c18764e3b03fd4fbarchard@google.com return false; 230946b817d939765bef587c575720c18764e3b03fd4fbarchard@google.com#endif 231032b4e2f2d38cb8fe7ca95ea0ab65ba4769ffa230niklas.enbom@webrtc.org} 2311b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} // namespace webrtc 2312