blob: 8e9485cb2a3057f83cdfe2aa9ab02c8fc2488100 [file] [log] [blame]
niklase@google.com470e71d2011-07-07 08:21:25 +00001/*
xians@webrtc.org79af7342012-01-31 12:22:14 +00002 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
niklase@google.com470e71d2011-07-07 08:21:25 +00003 *
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
pbos@webrtc.org956aa7e2013-05-21 13:52:32 +000011#include "webrtc/voice_engine/voe_hardware_impl.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000012
pbos@webrtc.org12dc1a32013-08-05 16:22:53 +000013#include <assert.h>
niklase@google.com470e71d2011-07-07 08:21:25 +000014
pbos@webrtc.org956aa7e2013-05-21 13:52:32 +000015#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
16#include "webrtc/system_wrappers/interface/trace.h"
17#include "webrtc/voice_engine/include/voe_errors.h"
18#include "webrtc/voice_engine/voice_engine_impl.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000019
Jelena Marusic0d266052015-05-04 14:15:32 +020020namespace webrtc {
niklase@google.com470e71d2011-07-07 08:21:25 +000021
Jelena Marusic0d266052015-05-04 14:15:32 +020022VoEHardware* VoEHardware::GetInterface(VoiceEngine* voiceEngine) {
niklase@google.com470e71d2011-07-07 08:21:25 +000023#ifndef WEBRTC_VOICE_ENGINE_HARDWARE_API
Jelena Marusic0d266052015-05-04 14:15:32 +020024 return NULL;
niklase@google.com470e71d2011-07-07 08:21:25 +000025#else
Jelena Marusic0d266052015-05-04 14:15:32 +020026 if (NULL == voiceEngine) {
27 return NULL;
28 }
29 VoiceEngineImpl* s = static_cast<VoiceEngineImpl*>(voiceEngine);
30 s->AddRef();
31 return s;
niklase@google.com470e71d2011-07-07 08:21:25 +000032#endif
33}
34
35#ifdef WEBRTC_VOICE_ENGINE_HARDWARE_API
36
Jelena Marusic0d266052015-05-04 14:15:32 +020037VoEHardwareImpl::VoEHardwareImpl(voe::SharedData* shared) : _shared(shared) {
38 WEBRTC_TRACE(kTraceMemory, kTraceVoice, VoEId(_shared->instance_id(), -1),
39 "VoEHardwareImpl() - ctor");
niklase@google.com470e71d2011-07-07 08:21:25 +000040}
41
Jelena Marusic0d266052015-05-04 14:15:32 +020042VoEHardwareImpl::~VoEHardwareImpl() {
43 WEBRTC_TRACE(kTraceMemory, kTraceVoice, VoEId(_shared->instance_id(), -1),
44 "~VoEHardwareImpl() - dtor");
niklase@google.com470e71d2011-07-07 08:21:25 +000045}
46
Jelena Marusic0d266052015-05-04 14:15:32 +020047int VoEHardwareImpl::SetAudioDeviceLayer(AudioLayers audioLayer) {
48 WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
49 "SetAudioDeviceLayer(audioLayer=%d)", audioLayer);
niklase@google.com470e71d2011-07-07 08:21:25 +000050
Jelena Marusic0d266052015-05-04 14:15:32 +020051 // 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 }
niklase@google.com470e71d2011-07-07 08:21:25 +000056
Jelena Marusic0d266052015-05-04 14:15:32 +020057 // 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 }
niklase@google.com470e71d2011-07-07 08:21:25 +000077
Jelena Marusic0d266052015-05-04 14:15:32 +020078 // Save the audio device layer for Init()
79 _shared->set_audio_device_layer(wantedLayer);
niklase@google.com470e71d2011-07-07 08:21:25 +000080
Jelena Marusic0d266052015-05-04 14:15:32 +020081 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +000082}
83
Jelena Marusic0d266052015-05-04 14:15:32 +020084int VoEHardwareImpl::GetAudioDeviceLayer(AudioLayers& audioLayer) {
85 WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
niklase@google.com470e71d2011-07-07 08:21:25 +000086 "GetAudioDeviceLayer(devices=?)");
87
Jelena Marusic0d266052015-05-04 14:15:32 +020088 // Can always be called regardless of VoE state
niklase@google.com470e71d2011-07-07 08:21:25 +000089
Jelena Marusic0d266052015-05-04 14:15:32 +020090 AudioDeviceModule::AudioLayer activeLayer(
91 AudioDeviceModule::kPlatformDefaultAudio);
niklase@google.com470e71d2011-07-07 08:21:25 +000092
Jelena Marusic0d266052015-05-04 14:15:32 +020093 if (_shared->audio_device()) {
94 // Get active audio layer from ADM
95 if (_shared->audio_device()->ActiveAudioLayer(&activeLayer) != 0) {
96 _shared->SetLastError(VE_UNDEFINED_SC_ERR, kTraceError,
97 " Audio Device error");
98 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +000099 }
Jelena Marusic0d266052015-05-04 14:15:32 +0200100 } else {
101 // Return VoE's internal layer setting
102 activeLayer = _shared->audio_device_layer();
103 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000104
Jelena Marusic0d266052015-05-04 14:15:32 +0200105 // Map to AudioLayers
106 switch (activeLayer) {
107 case AudioDeviceModule::kPlatformDefaultAudio:
108 audioLayer = kAudioPlatformDefault;
109 break;
110 case AudioDeviceModule::kWindowsCoreAudio:
111 audioLayer = kAudioWindowsCore;
112 break;
113 case AudioDeviceModule::kWindowsWaveAudio:
114 audioLayer = kAudioWindowsWave;
115 break;
116 case AudioDeviceModule::kLinuxAlsaAudio:
117 audioLayer = kAudioLinuxAlsa;
118 break;
119 case AudioDeviceModule::kLinuxPulseAudio:
120 audioLayer = kAudioLinuxPulse;
121 break;
122 default:
123 _shared->SetLastError(VE_UNDEFINED_SC_ERR, kTraceError,
124 " unknown audio layer");
125 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000126
Jelena Marusic0d266052015-05-04 14:15:32 +0200127 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, VoEId(_shared->instance_id(), -1),
128 " Output: audioLayer=%d", audioLayer);
niklase@google.com470e71d2011-07-07 08:21:25 +0000129
Jelena Marusic0d266052015-05-04 14:15:32 +0200130 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000131}
Jelena Marusic0d266052015-05-04 14:15:32 +0200132int VoEHardwareImpl::GetNumOfRecordingDevices(int& devices) {
133 WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
134 "GetNumOfRecordingDevices(devices=?)");
niklase@google.com470e71d2011-07-07 08:21:25 +0000135
Jelena Marusic0d266052015-05-04 14:15:32 +0200136 if (!_shared->statistics().Initialized()) {
137 _shared->SetLastError(VE_NOT_INITED, kTraceError);
138 return -1;
139 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000140
Jelena Marusic0d266052015-05-04 14:15:32 +0200141 devices = static_cast<int>(_shared->audio_device()->RecordingDevices());
niklase@google.com470e71d2011-07-07 08:21:25 +0000142
Jelena Marusic0d266052015-05-04 14:15:32 +0200143 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, VoEId(_shared->instance_id(), -1),
144 " Output: devices=%d", devices);
niklase@google.com470e71d2011-07-07 08:21:25 +0000145
Jelena Marusic0d266052015-05-04 14:15:32 +0200146 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000147}
148
Jelena Marusic0d266052015-05-04 14:15:32 +0200149int VoEHardwareImpl::GetNumOfPlayoutDevices(int& devices) {
150 WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
151 "GetNumOfPlayoutDevices(devices=?)");
niklase@google.com470e71d2011-07-07 08:21:25 +0000152
Jelena Marusic0d266052015-05-04 14:15:32 +0200153 if (!_shared->statistics().Initialized()) {
154 _shared->SetLastError(VE_NOT_INITED, kTraceError);
155 return -1;
156 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000157
Jelena Marusic0d266052015-05-04 14:15:32 +0200158 devices = static_cast<int>(_shared->audio_device()->PlayoutDevices());
niklase@google.com470e71d2011-07-07 08:21:25 +0000159
Jelena Marusic0d266052015-05-04 14:15:32 +0200160 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, VoEId(_shared->instance_id(), -1),
161 " Output: devices=%d", devices);
niklase@google.com470e71d2011-07-07 08:21:25 +0000162
Jelena Marusic0d266052015-05-04 14:15:32 +0200163 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000164}
165
166int VoEHardwareImpl::GetRecordingDeviceName(int index,
167 char strNameUTF8[128],
Jelena Marusic0d266052015-05-04 14:15:32 +0200168 char strGuidUTF8[128]) {
169 WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
170 "GetRecordingDeviceName(index=%d)", index);
niklase@google.com470e71d2011-07-07 08:21:25 +0000171
Jelena Marusic0d266052015-05-04 14:15:32 +0200172 if (!_shared->statistics().Initialized()) {
173 _shared->SetLastError(VE_NOT_INITED, kTraceError);
174 return -1;
175 }
176 if (strNameUTF8 == NULL) {
177 _shared->SetLastError(VE_INVALID_ARGUMENT, kTraceError,
178 "GetRecordingDeviceName() invalid argument");
179 return -1;
180 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000181
Jelena Marusic0d266052015-05-04 14:15:32 +0200182 // Note that strGuidUTF8 is allowed to be NULL
niklase@google.com470e71d2011-07-07 08:21:25 +0000183
Jelena Marusic0d266052015-05-04 14:15:32 +0200184 // Init len variable to length of supplied vectors
185 const uint16_t strLen = 128;
niklase@google.com470e71d2011-07-07 08:21:25 +0000186
Jelena Marusic0d266052015-05-04 14:15:32 +0200187 // Check if length has been changed in module
188 assert(strLen == kAdmMaxDeviceNameSize);
189 assert(strLen == kAdmMaxGuidSize);
niklase@google.com470e71d2011-07-07 08:21:25 +0000190
Jelena Marusic0d266052015-05-04 14:15:32 +0200191 char name[strLen];
192 char guid[strLen];
niklase@google.com470e71d2011-07-07 08:21:25 +0000193
Jelena Marusic0d266052015-05-04 14:15:32 +0200194 // Get names from module
195 if (_shared->audio_device()->RecordingDeviceName(index, name, guid) != 0) {
196 _shared->SetLastError(VE_CANNOT_RETRIEVE_DEVICE_NAME, kTraceError,
197 "GetRecordingDeviceName() failed to get device name");
198 return -1;
199 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000200
Jelena Marusic0d266052015-05-04 14:15:32 +0200201 // Copy to vectors supplied by user
202 strncpy(strNameUTF8, name, strLen);
203 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, VoEId(_shared->instance_id(), -1),
204 " Output: strNameUTF8=%s", strNameUTF8);
205
206 if (strGuidUTF8 != NULL) {
207 strncpy(strGuidUTF8, guid, strLen);
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000208 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
Jelena Marusic0d266052015-05-04 14:15:32 +0200209 VoEId(_shared->instance_id(), -1), " Output: strGuidUTF8=%s",
210 strGuidUTF8);
211 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000212
Jelena Marusic0d266052015-05-04 14:15:32 +0200213 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000214}
215
216int VoEHardwareImpl::GetPlayoutDeviceName(int index,
217 char strNameUTF8[128],
Jelena Marusic0d266052015-05-04 14:15:32 +0200218 char strGuidUTF8[128]) {
219 WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
220 "GetPlayoutDeviceName(index=%d)", index);
niklase@google.com470e71d2011-07-07 08:21:25 +0000221
Jelena Marusic0d266052015-05-04 14:15:32 +0200222 if (!_shared->statistics().Initialized()) {
223 _shared->SetLastError(VE_NOT_INITED, kTraceError);
224 return -1;
225 }
226 if (strNameUTF8 == NULL) {
227 _shared->SetLastError(VE_INVALID_ARGUMENT, kTraceError,
228 "GetPlayoutDeviceName() invalid argument");
229 return -1;
230 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000231
Jelena Marusic0d266052015-05-04 14:15:32 +0200232 // Note that strGuidUTF8 is allowed to be NULL
niklase@google.com470e71d2011-07-07 08:21:25 +0000233
Jelena Marusic0d266052015-05-04 14:15:32 +0200234 // Init len variable to length of supplied vectors
235 const uint16_t strLen = 128;
niklase@google.com470e71d2011-07-07 08:21:25 +0000236
Jelena Marusic0d266052015-05-04 14:15:32 +0200237 // Check if length has been changed in module
238 assert(strLen == kAdmMaxDeviceNameSize);
239 assert(strLen == kAdmMaxGuidSize);
niklase@google.com470e71d2011-07-07 08:21:25 +0000240
Jelena Marusic0d266052015-05-04 14:15:32 +0200241 char name[strLen];
242 char guid[strLen];
niklase@google.com470e71d2011-07-07 08:21:25 +0000243
Jelena Marusic0d266052015-05-04 14:15:32 +0200244 // Get names from module
245 if (_shared->audio_device()->PlayoutDeviceName(index, name, guid) != 0) {
246 _shared->SetLastError(VE_CANNOT_RETRIEVE_DEVICE_NAME, kTraceError,
247 "GetPlayoutDeviceName() failed to get device name");
248 return -1;
249 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000250
Jelena Marusic0d266052015-05-04 14:15:32 +0200251 // Copy to vectors supplied by user
252 strncpy(strNameUTF8, name, strLen);
253 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, VoEId(_shared->instance_id(), -1),
254 " Output: strNameUTF8=%s", strNameUTF8);
255
256 if (strGuidUTF8 != NULL) {
257 strncpy(strGuidUTF8, guid, strLen);
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000258 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
Jelena Marusic0d266052015-05-04 14:15:32 +0200259 VoEId(_shared->instance_id(), -1), " Output: strGuidUTF8=%s",
260 strGuidUTF8);
261 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000262
Jelena Marusic0d266052015-05-04 14:15:32 +0200263 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000264}
265
266int VoEHardwareImpl::SetRecordingDevice(int index,
Jelena Marusic0d266052015-05-04 14:15:32 +0200267 StereoChannel recordingChannel) {
268 WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
269 "SetRecordingDevice(index=%d, recordingChannel=%d)", index,
270 (int)recordingChannel);
271 CriticalSectionScoped cs(_shared->crit_sec());
niklase@google.com470e71d2011-07-07 08:21:25 +0000272
Jelena Marusic0d266052015-05-04 14:15:32 +0200273 if (!_shared->statistics().Initialized()) {
274 _shared->SetLastError(VE_NOT_INITED, kTraceError);
275 return -1;
276 }
277
278 bool isRecording(false);
279
280 // Store state about activated recording to be able to restore it after the
281 // recording device has been modified.
282 if (_shared->audio_device()->Recording()) {
283 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_shared->instance_id(), -1),
284 "SetRecordingDevice() device is modified while recording"
285 " is active...");
286 isRecording = true;
287 if (_shared->audio_device()->StopRecording() == -1) {
288 _shared->SetLastError(VE_AUDIO_DEVICE_MODULE_ERROR, kTraceError,
289 "SetRecordingDevice() unable to stop recording");
290 return -1;
291 }
292 }
293
294 // We let the module do the index sanity
295
296 // Set recording channel
297 AudioDeviceModule::ChannelType recCh = AudioDeviceModule::kChannelBoth;
298 switch (recordingChannel) {
299 case kStereoLeft:
300 recCh = AudioDeviceModule::kChannelLeft;
301 break;
302 case kStereoRight:
303 recCh = AudioDeviceModule::kChannelRight;
304 break;
305 case kStereoBoth:
306 // default setting kChannelBoth (<=> mono)
307 break;
308 }
309
310 if (_shared->audio_device()->SetRecordingChannel(recCh) != 0) {
311 _shared->SetLastError(
312 VE_AUDIO_DEVICE_MODULE_ERROR, kTraceWarning,
313 "SetRecordingChannel() unable to set the recording channel");
314 }
315
316 // Map indices to unsigned since underlying functions need that
317 uint16_t indexU = static_cast<uint16_t>(index);
318
319 int32_t res(0);
320
321 if (index == -1) {
322 res = _shared->audio_device()->SetRecordingDevice(
323 AudioDeviceModule::kDefaultCommunicationDevice);
324 } else if (index == -2) {
325 res = _shared->audio_device()->SetRecordingDevice(
326 AudioDeviceModule::kDefaultDevice);
327 } else {
328 res = _shared->audio_device()->SetRecordingDevice(indexU);
329 }
330
331 if (res != 0) {
332 _shared->SetLastError(
333 VE_AUDIO_DEVICE_MODULE_ERROR, kTraceError,
334 "SetRecordingDevice() unable to set the recording device");
335 return -1;
336 }
337
338 // Init microphone, so user can do volume settings etc
339 if (_shared->audio_device()->InitMicrophone() == -1) {
340 _shared->SetLastError(VE_CANNOT_ACCESS_MIC_VOL, kTraceWarning,
341 "SetRecordingDevice() cannot access microphone");
342 }
343
344 // Set number of channels
345 bool available = false;
346 if (_shared->audio_device()->StereoRecordingIsAvailable(&available) != 0) {
347 _shared->SetLastError(
348 VE_SOUNDCARD_ERROR, kTraceWarning,
349 "StereoRecordingIsAvailable() failed to query stereo recording");
350 }
351
352 if (_shared->audio_device()->SetStereoRecording(available) != 0) {
353 _shared->SetLastError(
354 VE_SOUNDCARD_ERROR, kTraceWarning,
355 "SetRecordingDevice() failed to set mono recording mode");
356 }
357
358 // Restore recording if it was enabled already when calling this function.
359 if (isRecording) {
360 if (!_shared->ext_recording()) {
361 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_shared->instance_id(), -1),
362 "SetRecordingDevice() recording is now being restored...");
363 if (_shared->audio_device()->InitRecording() != 0) {
364 WEBRTC_TRACE(kTraceError, kTraceVoice,
365 VoEId(_shared->instance_id(), -1),
366 "SetRecordingDevice() failed to initialize recording");
niklase@google.com470e71d2011-07-07 08:21:25 +0000367 return -1;
Jelena Marusic0d266052015-05-04 14:15:32 +0200368 }
369 if (_shared->audio_device()->StartRecording() != 0) {
370 WEBRTC_TRACE(kTraceError, kTraceVoice,
371 VoEId(_shared->instance_id(), -1),
372 "SetRecordingDevice() failed to start recording");
niklase@google.com470e71d2011-07-07 08:21:25 +0000373 return -1;
Jelena Marusic0d266052015-05-04 14:15:32 +0200374 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000375 }
Jelena Marusic0d266052015-05-04 14:15:32 +0200376 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000377
Jelena Marusic0d266052015-05-04 14:15:32 +0200378 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000379}
380
Jelena Marusic0d266052015-05-04 14:15:32 +0200381int VoEHardwareImpl::SetPlayoutDevice(int index) {
382 WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
383 "SetPlayoutDevice(index=%d)", index);
384 CriticalSectionScoped cs(_shared->crit_sec());
niklase@google.com470e71d2011-07-07 08:21:25 +0000385
Jelena Marusic0d266052015-05-04 14:15:32 +0200386 if (!_shared->statistics().Initialized()) {
387 _shared->SetLastError(VE_NOT_INITED, kTraceError);
388 return -1;
389 }
390
391 bool isPlaying(false);
392
393 // Store state about activated playout to be able to restore it after the
394 // playout device has been modified.
395 if (_shared->audio_device()->Playing()) {
396 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_shared->instance_id(), -1),
397 "SetPlayoutDevice() device is modified while playout is "
398 "active...");
399 isPlaying = true;
400 if (_shared->audio_device()->StopPlayout() == -1) {
401 _shared->SetLastError(VE_AUDIO_DEVICE_MODULE_ERROR, kTraceError,
402 "SetPlayoutDevice() unable to stop playout");
403 return -1;
404 }
405 }
406
407 // We let the module do the index sanity
408
409 // Map indices to unsigned since underlying functions need that
410 uint16_t indexU = static_cast<uint16_t>(index);
411
412 int32_t res(0);
413
414 if (index == -1) {
415 res = _shared->audio_device()->SetPlayoutDevice(
416 AudioDeviceModule::kDefaultCommunicationDevice);
417 } else if (index == -2) {
418 res = _shared->audio_device()->SetPlayoutDevice(
419 AudioDeviceModule::kDefaultDevice);
420 } else {
421 res = _shared->audio_device()->SetPlayoutDevice(indexU);
422 }
423
424 if (res != 0) {
425 _shared->SetLastError(
426 VE_SOUNDCARD_ERROR, kTraceError,
427 "SetPlayoutDevice() unable to set the playout device");
428 return -1;
429 }
430
431 // Init speaker, so user can do volume settings etc
432 if (_shared->audio_device()->InitSpeaker() == -1) {
433 _shared->SetLastError(VE_CANNOT_ACCESS_SPEAKER_VOL, kTraceWarning,
434 "SetPlayoutDevice() cannot access speaker");
435 }
436
437 // Set number of channels
438 bool available = false;
439 _shared->audio_device()->StereoPlayoutIsAvailable(&available);
440 if (_shared->audio_device()->SetStereoPlayout(available) != 0) {
441 _shared->SetLastError(
442 VE_SOUNDCARD_ERROR, kTraceWarning,
443 "SetPlayoutDevice() failed to set stereo playout mode");
444 }
445
446 // Restore playout if it was enabled already when calling this function.
447 if (isPlaying) {
448 if (!_shared->ext_playout()) {
449 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_shared->instance_id(), -1),
450 "SetPlayoutDevice() playout is now being restored...");
451 if (_shared->audio_device()->InitPlayout() != 0) {
452 WEBRTC_TRACE(kTraceError, kTraceVoice,
453 VoEId(_shared->instance_id(), -1),
454 "SetPlayoutDevice() failed to initialize playout");
niklase@google.com470e71d2011-07-07 08:21:25 +0000455 return -1;
Jelena Marusic0d266052015-05-04 14:15:32 +0200456 }
457 if (_shared->audio_device()->StartPlayout() != 0) {
458 WEBRTC_TRACE(kTraceError, kTraceVoice,
459 VoEId(_shared->instance_id(), -1),
460 "SetPlayoutDevice() failed to start playout");
niklase@google.com470e71d2011-07-07 08:21:25 +0000461 return -1;
Jelena Marusic0d266052015-05-04 14:15:32 +0200462 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000463 }
Jelena Marusic0d266052015-05-04 14:15:32 +0200464 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000465
Jelena Marusic0d266052015-05-04 14:15:32 +0200466 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000467}
468
leozwang@webrtc.org96bcac82012-12-04 19:11:55 +0000469int VoEHardwareImpl::SetRecordingSampleRate(unsigned int samples_per_sec) {
470 WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
471 "%s", __FUNCTION__);
472 if (!_shared->statistics().Initialized()) {
473 _shared->SetLastError(VE_NOT_INITED, kTraceError);
474 return false;
475 }
476 return _shared->audio_device()->SetRecordingSampleRate(samples_per_sec);
477}
478
479int VoEHardwareImpl::RecordingSampleRate(unsigned int* samples_per_sec) const {
480 WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
481 "%s", __FUNCTION__);
482 if (!_shared->statistics().Initialized()) {
483 _shared->SetLastError(VE_NOT_INITED, kTraceError);
484 return false;
485 }
486 return _shared->audio_device()->RecordingSampleRate(samples_per_sec);
487}
488
489int VoEHardwareImpl::SetPlayoutSampleRate(unsigned int samples_per_sec) {
490 WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
491 "%s", __FUNCTION__);
492 if (!_shared->statistics().Initialized()) {
493 _shared->SetLastError(VE_NOT_INITED, kTraceError);
494 return false;
495 }
496 return _shared->audio_device()->SetPlayoutSampleRate(samples_per_sec);
497}
498
499int VoEHardwareImpl::PlayoutSampleRate(unsigned int* samples_per_sec) const {
500 WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
501 "%s", __FUNCTION__);
502 if (!_shared->statistics().Initialized()) {
503 _shared->SetLastError(VE_NOT_INITED, kTraceError);
504 return false;
505 }
506 return _shared->audio_device()->PlayoutSampleRate(samples_per_sec);
507}
508
henrika@webrtc.orga954c072014-12-09 16:22:09 +0000509bool VoEHardwareImpl::BuiltInAECIsAvailable() const {
Jelena Marusic0d266052015-05-04 14:15:32 +0200510 if (!_shared->statistics().Initialized()) {
henrika@webrtc.orga954c072014-12-09 16:22:09 +0000511 _shared->SetLastError(VE_NOT_INITED, kTraceError);
512 return false;
513 }
514 return _shared->audio_device()->BuiltInAECIsAvailable();
515}
516
517int VoEHardwareImpl::EnableBuiltInAEC(bool enable) {
Jelena Marusic0d266052015-05-04 14:15:32 +0200518 if (!_shared->statistics().Initialized()) {
henrika@webrtc.orga954c072014-12-09 16:22:09 +0000519 _shared->SetLastError(VE_NOT_INITED, kTraceError);
Bjorn Volcker1d83f1e2015-04-07 15:25:39 +0200520 return -1;
henrika@webrtc.orga954c072014-12-09 16:22:09 +0000521 }
522 return _shared->audio_device()->EnableBuiltInAEC(enable);
523}
524
niklase@google.com470e71d2011-07-07 08:21:25 +0000525#endif // WEBRTC_VOICE_ENGINE_HARDWARE_API
526
pbos@webrtc.orgd900e8b2013-07-03 15:12:26 +0000527} // namespace webrtc