Home | History | Annotate | Download | only in voice_engine
      1 /*
      2  *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
      3  *
      4  *  Use of this source code is governed by a BSD-style license
      5  *  that can be found in the LICENSE file in the root of the source
      6  *  tree. An additional intellectual property rights grant can be found
      7  *  in the file PATENTS.  All contributing project authors may
      8  *  be found in the AUTHORS file in the root of the source tree.
      9  */
     10 
     11 #include "webrtc/voice_engine/voe_hardware_impl.h"
     12 
     13 #include <assert.h>
     14 
     15 #include "webrtc/system_wrappers/include/critical_section_wrapper.h"
     16 #include "webrtc/system_wrappers/include/trace.h"
     17 #include "webrtc/voice_engine/include/voe_errors.h"
     18 #include "webrtc/voice_engine/voice_engine_impl.h"
     19 
     20 namespace webrtc {
     21 
     22 VoEHardware* VoEHardware::GetInterface(VoiceEngine* voiceEngine) {
     23 #ifndef WEBRTC_VOICE_ENGINE_HARDWARE_API
     24   return NULL;
     25 #else
     26   if (NULL == voiceEngine) {
     27     return NULL;
     28   }
     29   VoiceEngineImpl* s = static_cast<VoiceEngineImpl*>(voiceEngine);
     30   s->AddRef();
     31   return s;
     32 #endif
     33 }
     34 
     35 #ifdef WEBRTC_VOICE_ENGINE_HARDWARE_API
     36 
     37 VoEHardwareImpl::VoEHardwareImpl(voe::SharedData* shared) : _shared(shared) {
     38   WEBRTC_TRACE(kTraceMemory, kTraceVoice, VoEId(_shared->instance_id(), -1),
     39                "VoEHardwareImpl() - ctor");
     40 }
     41 
     42 VoEHardwareImpl::~VoEHardwareImpl() {
     43   WEBRTC_TRACE(kTraceMemory, kTraceVoice, VoEId(_shared->instance_id(), -1),
     44                "~VoEHardwareImpl() - dtor");
     45 }
     46 
     47 int VoEHardwareImpl::SetAudioDeviceLayer(AudioLayers audioLayer) {
     48   WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
     49                "SetAudioDeviceLayer(audioLayer=%d)", audioLayer);
     50 
     51   // Don't allow a change if VoE is initialized
     52   if (_shared->statistics().Initialized()) {
     53     _shared->SetLastError(VE_ALREADY_INITED, kTraceError);
     54     return -1;
     55   }
     56 
     57   // Map to AudioDeviceModule::AudioLayer
     58   AudioDeviceModule::AudioLayer wantedLayer(
     59       AudioDeviceModule::kPlatformDefaultAudio);
     60   switch (audioLayer) {
     61     case kAudioPlatformDefault:
     62       // already set above
     63       break;
     64     case kAudioWindowsCore:
     65       wantedLayer = AudioDeviceModule::kWindowsCoreAudio;
     66       break;
     67     case kAudioWindowsWave:
     68       wantedLayer = AudioDeviceModule::kWindowsWaveAudio;
     69       break;
     70     case kAudioLinuxAlsa:
     71       wantedLayer = AudioDeviceModule::kLinuxAlsaAudio;
     72       break;
     73     case kAudioLinuxPulse:
     74       wantedLayer = AudioDeviceModule::kLinuxPulseAudio;
     75       break;
     76   }
     77 
     78   // Save the audio device layer for Init()
     79   _shared->set_audio_device_layer(wantedLayer);
     80 
     81   return 0;
     82 }
     83 
     84 int VoEHardwareImpl::GetAudioDeviceLayer(AudioLayers& audioLayer) {
     85   // Can always be called regardless of VoE state
     86 
     87   AudioDeviceModule::AudioLayer activeLayer(
     88       AudioDeviceModule::kPlatformDefaultAudio);
     89 
     90   if (_shared->audio_device()) {
     91     // Get active audio layer from ADM
     92     if (_shared->audio_device()->ActiveAudioLayer(&activeLayer) != 0) {
     93       _shared->SetLastError(VE_UNDEFINED_SC_ERR, kTraceError,
     94                             "  Audio Device error");
     95       return -1;
     96     }
     97   } else {
     98     // Return VoE's internal layer setting
     99     activeLayer = _shared->audio_device_layer();
    100   }
    101 
    102   // Map to AudioLayers
    103   switch (activeLayer) {
    104     case AudioDeviceModule::kPlatformDefaultAudio:
    105       audioLayer = kAudioPlatformDefault;
    106       break;
    107     case AudioDeviceModule::kWindowsCoreAudio:
    108       audioLayer = kAudioWindowsCore;
    109       break;
    110     case AudioDeviceModule::kWindowsWaveAudio:
    111       audioLayer = kAudioWindowsWave;
    112       break;
    113     case AudioDeviceModule::kLinuxAlsaAudio:
    114       audioLayer = kAudioLinuxAlsa;
    115       break;
    116     case AudioDeviceModule::kLinuxPulseAudio:
    117       audioLayer = kAudioLinuxPulse;
    118       break;
    119     default:
    120       _shared->SetLastError(VE_UNDEFINED_SC_ERR, kTraceError,
    121                             "  unknown audio layer");
    122   }
    123 
    124   return 0;
    125 }
    126 int VoEHardwareImpl::GetNumOfRecordingDevices(int& devices) {
    127   if (!_shared->statistics().Initialized()) {
    128     _shared->SetLastError(VE_NOT_INITED, kTraceError);
    129     return -1;
    130   }
    131 
    132   devices = static_cast<int>(_shared->audio_device()->RecordingDevices());
    133 
    134   return 0;
    135 }
    136 
    137 int VoEHardwareImpl::GetNumOfPlayoutDevices(int& devices) {
    138   if (!_shared->statistics().Initialized()) {
    139     _shared->SetLastError(VE_NOT_INITED, kTraceError);
    140     return -1;
    141   }
    142 
    143   devices = static_cast<int>(_shared->audio_device()->PlayoutDevices());
    144 
    145   return 0;
    146 }
    147 
    148 int VoEHardwareImpl::GetRecordingDeviceName(int index,
    149                                             char strNameUTF8[128],
    150                                             char strGuidUTF8[128]) {
    151   if (!_shared->statistics().Initialized()) {
    152     _shared->SetLastError(VE_NOT_INITED, kTraceError);
    153     return -1;
    154   }
    155   if (strNameUTF8 == NULL) {
    156     _shared->SetLastError(VE_INVALID_ARGUMENT, kTraceError,
    157                           "GetRecordingDeviceName() invalid argument");
    158     return -1;
    159   }
    160 
    161   // Note that strGuidUTF8 is allowed to be NULL
    162 
    163   // Init len variable to length of supplied vectors
    164   const uint16_t strLen = 128;
    165 
    166   // Check if length has been changed in module
    167   static_assert(strLen == kAdmMaxDeviceNameSize, "");
    168   static_assert(strLen == kAdmMaxGuidSize, "");
    169 
    170   char name[strLen];
    171   char guid[strLen];
    172 
    173   // Get names from module
    174   if (_shared->audio_device()->RecordingDeviceName(index, name, guid) != 0) {
    175     _shared->SetLastError(VE_CANNOT_RETRIEVE_DEVICE_NAME, kTraceError,
    176                           "GetRecordingDeviceName() failed to get device name");
    177     return -1;
    178   }
    179 
    180   // Copy to vectors supplied by user
    181   strncpy(strNameUTF8, name, strLen);
    182 
    183   if (strGuidUTF8 != NULL) {
    184     strncpy(strGuidUTF8, guid, strLen);
    185   }
    186 
    187   return 0;
    188 }
    189 
    190 int VoEHardwareImpl::GetPlayoutDeviceName(int index,
    191                                           char strNameUTF8[128],
    192                                           char strGuidUTF8[128]) {
    193   if (!_shared->statistics().Initialized()) {
    194     _shared->SetLastError(VE_NOT_INITED, kTraceError);
    195     return -1;
    196   }
    197   if (strNameUTF8 == NULL) {
    198     _shared->SetLastError(VE_INVALID_ARGUMENT, kTraceError,
    199                           "GetPlayoutDeviceName() invalid argument");
    200     return -1;
    201   }
    202 
    203   // Note that strGuidUTF8 is allowed to be NULL
    204 
    205   // Init len variable to length of supplied vectors
    206   const uint16_t strLen = 128;
    207 
    208   // Check if length has been changed in module
    209   static_assert(strLen == kAdmMaxDeviceNameSize, "");
    210   static_assert(strLen == kAdmMaxGuidSize, "");
    211 
    212   char name[strLen];
    213   char guid[strLen];
    214 
    215   // Get names from module
    216   if (_shared->audio_device()->PlayoutDeviceName(index, name, guid) != 0) {
    217     _shared->SetLastError(VE_CANNOT_RETRIEVE_DEVICE_NAME, kTraceError,
    218                           "GetPlayoutDeviceName() failed to get device name");
    219     return -1;
    220   }
    221 
    222   // Copy to vectors supplied by user
    223   strncpy(strNameUTF8, name, strLen);
    224 
    225   if (strGuidUTF8 != NULL) {
    226     strncpy(strGuidUTF8, guid, strLen);
    227   }
    228 
    229   return 0;
    230 }
    231 
    232 int VoEHardwareImpl::SetRecordingDevice(int index,
    233                                         StereoChannel recordingChannel) {
    234   WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
    235                "SetRecordingDevice(index=%d, recordingChannel=%d)", index,
    236                (int)recordingChannel);
    237   CriticalSectionScoped cs(_shared->crit_sec());
    238 
    239   if (!_shared->statistics().Initialized()) {
    240     _shared->SetLastError(VE_NOT_INITED, kTraceError);
    241     return -1;
    242   }
    243 
    244   bool isRecording(false);
    245 
    246   // Store state about activated recording to be able to restore it after the
    247   // recording device has been modified.
    248   if (_shared->audio_device()->Recording()) {
    249     WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_shared->instance_id(), -1),
    250                  "SetRecordingDevice() device is modified while recording"
    251                  " is active...");
    252     isRecording = true;
    253     if (_shared->audio_device()->StopRecording() == -1) {
    254       _shared->SetLastError(VE_AUDIO_DEVICE_MODULE_ERROR, kTraceError,
    255                             "SetRecordingDevice() unable to stop recording");
    256       return -1;
    257     }
    258   }
    259 
    260   // We let the module do the index sanity
    261 
    262   // Set recording channel
    263   AudioDeviceModule::ChannelType recCh = AudioDeviceModule::kChannelBoth;
    264   switch (recordingChannel) {
    265     case kStereoLeft:
    266       recCh = AudioDeviceModule::kChannelLeft;
    267       break;
    268     case kStereoRight:
    269       recCh = AudioDeviceModule::kChannelRight;
    270       break;
    271     case kStereoBoth:
    272       // default setting kChannelBoth (<=> mono)
    273       break;
    274   }
    275 
    276   if (_shared->audio_device()->SetRecordingChannel(recCh) != 0) {
    277     _shared->SetLastError(
    278         VE_AUDIO_DEVICE_MODULE_ERROR, kTraceWarning,
    279         "SetRecordingChannel() unable to set the recording channel");
    280   }
    281 
    282   // Map indices to unsigned since underlying functions need that
    283   uint16_t indexU = static_cast<uint16_t>(index);
    284 
    285   int32_t res(0);
    286 
    287   if (index == -1) {
    288     res = _shared->audio_device()->SetRecordingDevice(
    289         AudioDeviceModule::kDefaultCommunicationDevice);
    290   } else if (index == -2) {
    291     res = _shared->audio_device()->SetRecordingDevice(
    292         AudioDeviceModule::kDefaultDevice);
    293   } else {
    294     res = _shared->audio_device()->SetRecordingDevice(indexU);
    295   }
    296 
    297   if (res != 0) {
    298     _shared->SetLastError(
    299         VE_AUDIO_DEVICE_MODULE_ERROR, kTraceError,
    300         "SetRecordingDevice() unable to set the recording device");
    301     return -1;
    302   }
    303 
    304   // Init microphone, so user can do volume settings etc
    305   if (_shared->audio_device()->InitMicrophone() == -1) {
    306     _shared->SetLastError(VE_CANNOT_ACCESS_MIC_VOL, kTraceWarning,
    307                           "SetRecordingDevice() cannot access microphone");
    308   }
    309 
    310   // Set number of channels
    311   bool available = false;
    312   if (_shared->audio_device()->StereoRecordingIsAvailable(&available) != 0) {
    313     _shared->SetLastError(
    314         VE_SOUNDCARD_ERROR, kTraceWarning,
    315         "StereoRecordingIsAvailable() failed to query stereo recording");
    316   }
    317 
    318   if (_shared->audio_device()->SetStereoRecording(available) != 0) {
    319     _shared->SetLastError(
    320         VE_SOUNDCARD_ERROR, kTraceWarning,
    321         "SetRecordingDevice() failed to set mono recording mode");
    322   }
    323 
    324   // Restore recording if it was enabled already when calling this function.
    325   if (isRecording) {
    326     WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_shared->instance_id(), -1),
    327                  "SetRecordingDevice() recording is now being restored...");
    328     if (_shared->audio_device()->InitRecording() != 0) {
    329       WEBRTC_TRACE(kTraceError, kTraceVoice,
    330                    VoEId(_shared->instance_id(), -1),
    331                    "SetRecordingDevice() failed to initialize recording");
    332       return -1;
    333     }
    334     if (_shared->audio_device()->StartRecording() != 0) {
    335       WEBRTC_TRACE(kTraceError, kTraceVoice,
    336                    VoEId(_shared->instance_id(), -1),
    337                    "SetRecordingDevice() failed to start recording");
    338       return -1;
    339     }
    340   }
    341 
    342   return 0;
    343 }
    344 
    345 int VoEHardwareImpl::SetPlayoutDevice(int index) {
    346   WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
    347                "SetPlayoutDevice(index=%d)", index);
    348   CriticalSectionScoped cs(_shared->crit_sec());
    349 
    350   if (!_shared->statistics().Initialized()) {
    351     _shared->SetLastError(VE_NOT_INITED, kTraceError);
    352     return -1;
    353   }
    354 
    355   bool isPlaying(false);
    356 
    357   // Store state about activated playout to be able to restore it after the
    358   // playout device has been modified.
    359   if (_shared->audio_device()->Playing()) {
    360     WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_shared->instance_id(), -1),
    361                  "SetPlayoutDevice() device is modified while playout is "
    362                  "active...");
    363     isPlaying = true;
    364     if (_shared->audio_device()->StopPlayout() == -1) {
    365       _shared->SetLastError(VE_AUDIO_DEVICE_MODULE_ERROR, kTraceError,
    366                             "SetPlayoutDevice() unable to stop playout");
    367       return -1;
    368     }
    369   }
    370 
    371   // We let the module do the index sanity
    372 
    373   // Map indices to unsigned since underlying functions need that
    374   uint16_t indexU = static_cast<uint16_t>(index);
    375 
    376   int32_t res(0);
    377 
    378   if (index == -1) {
    379     res = _shared->audio_device()->SetPlayoutDevice(
    380         AudioDeviceModule::kDefaultCommunicationDevice);
    381   } else if (index == -2) {
    382     res = _shared->audio_device()->SetPlayoutDevice(
    383         AudioDeviceModule::kDefaultDevice);
    384   } else {
    385     res = _shared->audio_device()->SetPlayoutDevice(indexU);
    386   }
    387 
    388   if (res != 0) {
    389     _shared->SetLastError(
    390         VE_SOUNDCARD_ERROR, kTraceError,
    391         "SetPlayoutDevice() unable to set the playout device");
    392     return -1;
    393   }
    394 
    395   // Init speaker, so user can do volume settings etc
    396   if (_shared->audio_device()->InitSpeaker() == -1) {
    397     _shared->SetLastError(VE_CANNOT_ACCESS_SPEAKER_VOL, kTraceWarning,
    398                           "SetPlayoutDevice() cannot access speaker");
    399   }
    400 
    401   // Set number of channels
    402   bool available = false;
    403   _shared->audio_device()->StereoPlayoutIsAvailable(&available);
    404   if (_shared->audio_device()->SetStereoPlayout(available) != 0) {
    405     _shared->SetLastError(
    406         VE_SOUNDCARD_ERROR, kTraceWarning,
    407         "SetPlayoutDevice() failed to set stereo playout mode");
    408   }
    409 
    410   // Restore playout if it was enabled already when calling this function.
    411   if (isPlaying) {
    412     WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_shared->instance_id(), -1),
    413                  "SetPlayoutDevice() playout is now being restored...");
    414     if (_shared->audio_device()->InitPlayout() != 0) {
    415       WEBRTC_TRACE(kTraceError, kTraceVoice,
    416                    VoEId(_shared->instance_id(), -1),
    417                    "SetPlayoutDevice() failed to initialize playout");
    418       return -1;
    419     }
    420     if (_shared->audio_device()->StartPlayout() != 0) {
    421       WEBRTC_TRACE(kTraceError, kTraceVoice,
    422                    VoEId(_shared->instance_id(), -1),
    423                    "SetPlayoutDevice() failed to start playout");
    424       return -1;
    425     }
    426   }
    427 
    428   return 0;
    429 }
    430 
    431 int VoEHardwareImpl::SetRecordingSampleRate(unsigned int samples_per_sec) {
    432   WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
    433                "%s", __FUNCTION__);
    434   if (!_shared->statistics().Initialized()) {
    435     _shared->SetLastError(VE_NOT_INITED, kTraceError);
    436     return false;
    437   }
    438   return _shared->audio_device()->SetRecordingSampleRate(samples_per_sec);
    439 }
    440 
    441 int VoEHardwareImpl::RecordingSampleRate(unsigned int* samples_per_sec) const {
    442   if (!_shared->statistics().Initialized()) {
    443     _shared->SetLastError(VE_NOT_INITED, kTraceError);
    444     return false;
    445   }
    446   return _shared->audio_device()->RecordingSampleRate(samples_per_sec);
    447 }
    448 
    449 int VoEHardwareImpl::SetPlayoutSampleRate(unsigned int samples_per_sec) {
    450   WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
    451                "%s", __FUNCTION__);
    452   if (!_shared->statistics().Initialized()) {
    453     _shared->SetLastError(VE_NOT_INITED, kTraceError);
    454     return false;
    455   }
    456   return _shared->audio_device()->SetPlayoutSampleRate(samples_per_sec);
    457 }
    458 
    459 int VoEHardwareImpl::PlayoutSampleRate(unsigned int* samples_per_sec) const {
    460   if (!_shared->statistics().Initialized()) {
    461     _shared->SetLastError(VE_NOT_INITED, kTraceError);
    462     return false;
    463   }
    464   return _shared->audio_device()->PlayoutSampleRate(samples_per_sec);
    465 }
    466 
    467 bool VoEHardwareImpl::BuiltInAECIsAvailable() const {
    468   if (!_shared->statistics().Initialized()) {
    469     _shared->SetLastError(VE_NOT_INITED, kTraceError);
    470     return false;
    471   }
    472   return _shared->audio_device()->BuiltInAECIsAvailable();
    473 }
    474 
    475 int VoEHardwareImpl::EnableBuiltInAEC(bool enable) {
    476   if (!_shared->statistics().Initialized()) {
    477     _shared->SetLastError(VE_NOT_INITED, kTraceError);
    478     return -1;
    479   }
    480   return _shared->audio_device()->EnableBuiltInAEC(enable);
    481 }
    482 
    483 bool VoEHardwareImpl::BuiltInAGCIsAvailable() const {
    484   if (!_shared->statistics().Initialized()) {
    485     _shared->SetLastError(VE_NOT_INITED, kTraceError);
    486     return false;
    487   }
    488   return _shared->audio_device()->BuiltInAGCIsAvailable();
    489 }
    490 
    491 int VoEHardwareImpl::EnableBuiltInAGC(bool enable) {
    492   if (!_shared->statistics().Initialized()) {
    493     _shared->SetLastError(VE_NOT_INITED, kTraceError);
    494     return -1;
    495   }
    496   return _shared->audio_device()->EnableBuiltInAGC(enable);
    497 }
    498 
    499 bool VoEHardwareImpl::BuiltInNSIsAvailable() const {
    500   if (!_shared->statistics().Initialized()) {
    501     _shared->SetLastError(VE_NOT_INITED, kTraceError);
    502     return false;
    503   }
    504   return _shared->audio_device()->BuiltInNSIsAvailable();
    505 }
    506 
    507 int VoEHardwareImpl::EnableBuiltInNS(bool enable) {
    508   if (!_shared->statistics().Initialized()) {
    509     _shared->SetLastError(VE_NOT_INITED, kTraceError);
    510     return -1;
    511   }
    512   return _shared->audio_device()->EnableBuiltInNS(enable);
    513 }
    514 
    515 #endif  // WEBRTC_VOICE_ENGINE_HARDWARE_API
    516 
    517 }  // namespace webrtc
    518