blob: eaf2a28a38a7e2263823b148523ec6b08ba485e1 [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
20namespace webrtc
21{
22
23VoEHardware* VoEHardware::GetInterface(VoiceEngine* voiceEngine)
24{
25#ifndef WEBRTC_VOICE_ENGINE_HARDWARE_API
26 return NULL;
27#else
28 if (NULL == voiceEngine)
29 {
30 return NULL;
31 }
tommi@webrtc.org0989fb72013-02-15 15:07:32 +000032 VoiceEngineImpl* s = static_cast<VoiceEngineImpl*>(voiceEngine);
tommi@webrtc.orga990e122012-04-26 15:28:22 +000033 s->AddRef();
34 return s;
niklase@google.com470e71d2011-07-07 08:21:25 +000035#endif
36}
37
38#ifdef WEBRTC_VOICE_ENGINE_HARDWARE_API
39
henrike@webrtc.org93bea512013-03-28 15:58:49 +000040VoEHardwareImpl::VoEHardwareImpl(voe::SharedData* shared) : _shared(shared)
niklase@google.com470e71d2011-07-07 08:21:25 +000041{
tommi@webrtc.org851becd2012-04-04 14:57:19 +000042 WEBRTC_TRACE(kTraceMemory, kTraceVoice, VoEId(_shared->instance_id(), -1),
niklase@google.com470e71d2011-07-07 08:21:25 +000043 "VoEHardwareImpl() - ctor");
niklase@google.com470e71d2011-07-07 08:21:25 +000044}
45
46VoEHardwareImpl::~VoEHardwareImpl()
47{
tommi@webrtc.org851becd2012-04-04 14:57:19 +000048 WEBRTC_TRACE(kTraceMemory, kTraceVoice, VoEId(_shared->instance_id(), -1),
niklase@google.com470e71d2011-07-07 08:21:25 +000049 "~VoEHardwareImpl() - dtor");
niklase@google.com470e71d2011-07-07 08:21:25 +000050}
51
niklase@google.com470e71d2011-07-07 08:21:25 +000052int VoEHardwareImpl::SetAudioDeviceLayer(AudioLayers audioLayer)
53{
tommi@webrtc.org851becd2012-04-04 14:57:19 +000054 WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
niklase@google.com470e71d2011-07-07 08:21:25 +000055 "SetAudioDeviceLayer(audioLayer=%d)", audioLayer);
56
57 // Don't allow a change if VoE is initialized
tommi@webrtc.org851becd2012-04-04 14:57:19 +000058 if (_shared->statistics().Initialized())
niklase@google.com470e71d2011-07-07 08:21:25 +000059 {
tommi@webrtc.org851becd2012-04-04 14:57:19 +000060 _shared->SetLastError(VE_ALREADY_INITED, kTraceError);
niklase@google.com470e71d2011-07-07 08:21:25 +000061 return -1;
62 }
63
64 // Map to AudioDeviceModule::AudioLayer
65 AudioDeviceModule::AudioLayer
66 wantedLayer(AudioDeviceModule::kPlatformDefaultAudio);
67 switch (audioLayer)
68 {
69 case kAudioPlatformDefault:
70 // already set above
71 break;
72 case kAudioWindowsCore:
73 wantedLayer = AudioDeviceModule::kWindowsCoreAudio;
74 break;
75 case kAudioWindowsWave:
76 wantedLayer = AudioDeviceModule::kWindowsWaveAudio;
77 break;
78 case kAudioLinuxAlsa:
79 wantedLayer = AudioDeviceModule::kLinuxAlsaAudio;
80 break;
81 case kAudioLinuxPulse:
82 wantedLayer = AudioDeviceModule::kLinuxPulseAudio;
83 break;
niklase@google.com470e71d2011-07-07 08:21:25 +000084 }
85
86 // Save the audio device layer for Init()
tommi@webrtc.org851becd2012-04-04 14:57:19 +000087 _shared->set_audio_device_layer(wantedLayer);
niklase@google.com470e71d2011-07-07 08:21:25 +000088
89 return 0;
90}
91
92int VoEHardwareImpl::GetAudioDeviceLayer(AudioLayers& audioLayer)
93{
tommi@webrtc.org851becd2012-04-04 14:57:19 +000094 WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
niklase@google.com470e71d2011-07-07 08:21:25 +000095 "GetAudioDeviceLayer(devices=?)");
96
97 // Can always be called regardless of VoE state
98
99 AudioDeviceModule::AudioLayer
100 activeLayer(AudioDeviceModule::kPlatformDefaultAudio);
101
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000102 if (_shared->audio_device())
niklase@google.com470e71d2011-07-07 08:21:25 +0000103 {
104 // Get active audio layer from ADM
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000105 if (_shared->audio_device()->ActiveAudioLayer(&activeLayer) != 0)
niklase@google.com470e71d2011-07-07 08:21:25 +0000106 {
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000107 _shared->SetLastError(VE_UNDEFINED_SC_ERR, kTraceError,
108 " Audio Device error");
niklase@google.com470e71d2011-07-07 08:21:25 +0000109 return -1;
110 }
111 }
112 else
113 {
114 // Return VoE's internal layer setting
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000115 activeLayer = _shared->audio_device_layer();
niklase@google.com470e71d2011-07-07 08:21:25 +0000116 }
117
118 // Map to AudioLayers
119 switch (activeLayer)
120 {
121 case AudioDeviceModule::kPlatformDefaultAudio:
122 audioLayer = kAudioPlatformDefault;
123 break;
124 case AudioDeviceModule::kWindowsCoreAudio:
125 audioLayer = kAudioWindowsCore;
126 break;
127 case AudioDeviceModule::kWindowsWaveAudio:
128 audioLayer = kAudioWindowsWave;
129 break;
130 case AudioDeviceModule::kLinuxAlsaAudio:
131 audioLayer = kAudioLinuxAlsa;
132 break;
133 case AudioDeviceModule::kLinuxPulseAudio:
134 audioLayer = kAudioLinuxPulse;
135 break;
136 default:
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000137 _shared->SetLastError(VE_UNDEFINED_SC_ERR, kTraceError,
138 " unknown audio layer");
niklase@google.com470e71d2011-07-07 08:21:25 +0000139 }
140
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000141 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
142 VoEId(_shared->instance_id(), -1),
143 " Output: audioLayer=%d", audioLayer);
niklase@google.com470e71d2011-07-07 08:21:25 +0000144
145 return 0;
146}
147int VoEHardwareImpl::GetNumOfRecordingDevices(int& devices)
148{
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000149 WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
niklase@google.com470e71d2011-07-07 08:21:25 +0000150 "GetNumOfRecordingDevices(devices=?)");
niklase@google.com470e71d2011-07-07 08:21:25 +0000151
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000152 if (!_shared->statistics().Initialized())
niklase@google.com470e71d2011-07-07 08:21:25 +0000153 {
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000154 _shared->SetLastError(VE_NOT_INITED, kTraceError);
niklase@google.com470e71d2011-07-07 08:21:25 +0000155 return -1;
156 }
157
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000158 devices = static_cast<int> (_shared->audio_device()->RecordingDevices());
niklase@google.com470e71d2011-07-07 08:21:25 +0000159
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000160 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
161 VoEId(_shared->instance_id(), -1), " Output: devices=%d", devices);
niklase@google.com470e71d2011-07-07 08:21:25 +0000162
163 return 0;
164}
165
166int VoEHardwareImpl::GetNumOfPlayoutDevices(int& devices)
167{
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000168 WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
niklase@google.com470e71d2011-07-07 08:21:25 +0000169 "GetNumOfPlayoutDevices(devices=?)");
niklase@google.com470e71d2011-07-07 08:21:25 +0000170
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000171 if (!_shared->statistics().Initialized())
niklase@google.com470e71d2011-07-07 08:21:25 +0000172 {
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000173 _shared->SetLastError(VE_NOT_INITED, kTraceError);
niklase@google.com470e71d2011-07-07 08:21:25 +0000174 return -1;
175 }
176
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000177 devices = static_cast<int> (_shared->audio_device()->PlayoutDevices());
niklase@google.com470e71d2011-07-07 08:21:25 +0000178
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000179 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
180 VoEId(_shared->instance_id(), -1),
181 " Output: devices=%d", devices);
niklase@google.com470e71d2011-07-07 08:21:25 +0000182
183 return 0;
184}
185
186int VoEHardwareImpl::GetRecordingDeviceName(int index,
187 char strNameUTF8[128],
188 char strGuidUTF8[128])
189{
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000190 WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
niklase@google.com470e71d2011-07-07 08:21:25 +0000191 "GetRecordingDeviceName(index=%d)", index);
niklase@google.com470e71d2011-07-07 08:21:25 +0000192
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000193 if (!_shared->statistics().Initialized())
niklase@google.com470e71d2011-07-07 08:21:25 +0000194 {
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000195 _shared->SetLastError(VE_NOT_INITED, kTraceError);
niklase@google.com470e71d2011-07-07 08:21:25 +0000196 return -1;
197 }
198 if (strNameUTF8 == NULL)
199 {
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000200 _shared->SetLastError(VE_INVALID_ARGUMENT, kTraceError,
niklase@google.com470e71d2011-07-07 08:21:25 +0000201 "GetRecordingDeviceName() invalid argument");
202 return -1;
203 }
204
205 // Note that strGuidUTF8 is allowed to be NULL
206
207 // Init len variable to length of supplied vectors
pbos@webrtc.org6141e132013-04-09 10:09:10 +0000208 const uint16_t strLen = 128;
niklase@google.com470e71d2011-07-07 08:21:25 +0000209
210 // Check if length has been changed in module
211 assert(strLen == kAdmMaxDeviceNameSize);
212 assert(strLen == kAdmMaxGuidSize);
213
leozwang@webrtc.org813e4b02012-03-01 18:34:25 +0000214 char name[strLen];
215 char guid[strLen];
niklase@google.com470e71d2011-07-07 08:21:25 +0000216
217 // Get names from module
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000218 if (_shared->audio_device()->RecordingDeviceName(index, name, guid) != 0)
niklase@google.com470e71d2011-07-07 08:21:25 +0000219 {
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000220 _shared->SetLastError(VE_CANNOT_RETRIEVE_DEVICE_NAME, kTraceError,
niklase@google.com470e71d2011-07-07 08:21:25 +0000221 "GetRecordingDeviceName() failed to get device name");
222 return -1;
223 }
224
225 // Copy to vectors supplied by user
226 strncpy(strNameUTF8, name, strLen);
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000227 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
228 VoEId(_shared->instance_id(), -1),
229 " Output: strNameUTF8=%s", strNameUTF8);
niklase@google.com470e71d2011-07-07 08:21:25 +0000230
231 if (strGuidUTF8 != NULL)
232 {
xians@google.com49d025f2011-09-27 14:43:06 +0000233 strncpy(strGuidUTF8, guid, strLen);
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000234 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
235 VoEId(_shared->instance_id(), -1),
236 " Output: strGuidUTF8=%s", strGuidUTF8);
niklase@google.com470e71d2011-07-07 08:21:25 +0000237 }
238
239 return 0;
240}
241
242int VoEHardwareImpl::GetPlayoutDeviceName(int index,
243 char strNameUTF8[128],
244 char strGuidUTF8[128])
245{
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000246 WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
niklase@google.com470e71d2011-07-07 08:21:25 +0000247 "GetPlayoutDeviceName(index=%d)", index);
niklase@google.com470e71d2011-07-07 08:21:25 +0000248
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000249 if (!_shared->statistics().Initialized())
niklase@google.com470e71d2011-07-07 08:21:25 +0000250 {
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000251 _shared->SetLastError(VE_NOT_INITED, kTraceError);
niklase@google.com470e71d2011-07-07 08:21:25 +0000252 return -1;
253 }
254 if (strNameUTF8 == NULL)
255 {
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000256 _shared->SetLastError(VE_INVALID_ARGUMENT, kTraceError,
niklase@google.com470e71d2011-07-07 08:21:25 +0000257 "GetPlayoutDeviceName() invalid argument");
258 return -1;
259 }
260
261 // Note that strGuidUTF8 is allowed to be NULL
262
263 // Init len variable to length of supplied vectors
pbos@webrtc.org6141e132013-04-09 10:09:10 +0000264 const uint16_t strLen = 128;
niklase@google.com470e71d2011-07-07 08:21:25 +0000265
266 // Check if length has been changed in module
267 assert(strLen == kAdmMaxDeviceNameSize);
268 assert(strLen == kAdmMaxGuidSize);
269
leozwang@webrtc.org813e4b02012-03-01 18:34:25 +0000270 char name[strLen];
271 char guid[strLen];
niklase@google.com470e71d2011-07-07 08:21:25 +0000272
273 // Get names from module
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000274 if (_shared->audio_device()->PlayoutDeviceName(index, name, guid) != 0)
niklase@google.com470e71d2011-07-07 08:21:25 +0000275 {
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000276 _shared->SetLastError(VE_CANNOT_RETRIEVE_DEVICE_NAME, kTraceError,
niklase@google.com470e71d2011-07-07 08:21:25 +0000277 "GetPlayoutDeviceName() failed to get device name");
278 return -1;
279 }
280
281 // Copy to vectors supplied by user
282 strncpy(strNameUTF8, name, strLen);
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000283 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
284 VoEId(_shared->instance_id(), -1),
285 " Output: strNameUTF8=%s", strNameUTF8);
niklase@google.com470e71d2011-07-07 08:21:25 +0000286
287 if (strGuidUTF8 != NULL)
288 {
xians@google.comb8753492011-09-05 12:17:30 +0000289 strncpy(strGuidUTF8, guid, strLen);
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000290 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
291 VoEId(_shared->instance_id(), -1),
292 " Output: strGuidUTF8=%s", strGuidUTF8);
niklase@google.com470e71d2011-07-07 08:21:25 +0000293 }
294
295 return 0;
296}
297
298int VoEHardwareImpl::SetRecordingDevice(int index,
299 StereoChannel recordingChannel)
300{
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000301 WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
niklase@google.com470e71d2011-07-07 08:21:25 +0000302 "SetRecordingDevice(index=%d, recordingChannel=%d)",
303 index, (int) recordingChannel);
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000304 CriticalSectionScoped cs(_shared->crit_sec());
niklase@google.com470e71d2011-07-07 08:21:25 +0000305
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000306 if (!_shared->statistics().Initialized())
niklase@google.com470e71d2011-07-07 08:21:25 +0000307 {
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000308 _shared->SetLastError(VE_NOT_INITED, kTraceError);
niklase@google.com470e71d2011-07-07 08:21:25 +0000309 return -1;
310 }
311
312 bool isRecording(false);
313
314 // Store state about activated recording to be able to restore it after the
315 // recording device has been modified.
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000316 if (_shared->audio_device()->Recording())
niklase@google.com470e71d2011-07-07 08:21:25 +0000317 {
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000318 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_shared->instance_id(), -1),
niklase@google.com470e71d2011-07-07 08:21:25 +0000319 "SetRecordingDevice() device is modified while recording"
320 " is active...");
321 isRecording = true;
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000322 if (_shared->audio_device()->StopRecording() == -1)
niklase@google.com470e71d2011-07-07 08:21:25 +0000323 {
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000324 _shared->SetLastError(VE_AUDIO_DEVICE_MODULE_ERROR, kTraceError,
niklase@google.com470e71d2011-07-07 08:21:25 +0000325 "SetRecordingDevice() unable to stop recording");
326 return -1;
327 }
328 }
329
330 // We let the module do the index sanity
331
332 // Set recording channel
333 AudioDeviceModule::ChannelType recCh =
334 AudioDeviceModule::kChannelBoth;
335 switch (recordingChannel)
336 {
337 case kStereoLeft:
338 recCh = AudioDeviceModule::kChannelLeft;
339 break;
340 case kStereoRight:
341 recCh = AudioDeviceModule::kChannelRight;
342 break;
343 case kStereoBoth:
344 // default setting kChannelBoth (<=> mono)
345 break;
niklase@google.com470e71d2011-07-07 08:21:25 +0000346 }
347
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000348 if (_shared->audio_device()->SetRecordingChannel(recCh) != 0) {
349 _shared->SetLastError(VE_AUDIO_DEVICE_MODULE_ERROR, kTraceWarning,
xians@webrtc.org79af7342012-01-31 12:22:14 +0000350 "SetRecordingChannel() unable to set the recording channel");
351 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000352
353 // Map indices to unsigned since underlying functions need that
pbos@webrtc.org6141e132013-04-09 10:09:10 +0000354 uint16_t indexU = static_cast<uint16_t> (index);
niklase@google.com470e71d2011-07-07 08:21:25 +0000355
pbos@webrtc.org6141e132013-04-09 10:09:10 +0000356 int32_t res(0);
niklase@google.com470e71d2011-07-07 08:21:25 +0000357
358 if (index == -1)
359 {
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000360 res = _shared->audio_device()->SetRecordingDevice(
niklase@google.com470e71d2011-07-07 08:21:25 +0000361 AudioDeviceModule::kDefaultCommunicationDevice);
362 }
363 else if (index == -2)
364 {
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000365 res = _shared->audio_device()->SetRecordingDevice(
niklase@google.com470e71d2011-07-07 08:21:25 +0000366 AudioDeviceModule::kDefaultDevice);
367 }
368 else
369 {
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000370 res = _shared->audio_device()->SetRecordingDevice(indexU);
niklase@google.com470e71d2011-07-07 08:21:25 +0000371 }
372
373 if (res != 0)
374 {
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000375 _shared->SetLastError(VE_AUDIO_DEVICE_MODULE_ERROR, kTraceError,
niklase@google.com470e71d2011-07-07 08:21:25 +0000376 "SetRecordingDevice() unable to set the recording device");
377 return -1;
378 }
379
380 // Init microphone, so user can do volume settings etc
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000381 if (_shared->audio_device()->InitMicrophone() == -1)
niklase@google.com470e71d2011-07-07 08:21:25 +0000382 {
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000383 _shared->SetLastError(VE_CANNOT_ACCESS_MIC_VOL, kTraceWarning,
niklase@google.com470e71d2011-07-07 08:21:25 +0000384 "SetRecordingDevice() cannot access microphone");
385 }
386
387 // Set number of channels
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000388 bool available = false;
389 if (_shared->audio_device()->StereoRecordingIsAvailable(&available) != 0) {
390 _shared->SetLastError(VE_SOUNDCARD_ERROR, kTraceWarning,
xians@webrtc.org79af7342012-01-31 12:22:14 +0000391 "StereoRecordingIsAvailable() failed to query stereo recording");
392 }
393
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000394 if (_shared->audio_device()->SetStereoRecording(available) != 0)
niklase@google.com470e71d2011-07-07 08:21:25 +0000395 {
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000396 _shared->SetLastError(VE_SOUNDCARD_ERROR, kTraceWarning,
niklase@google.com470e71d2011-07-07 08:21:25 +0000397 "SetRecordingDevice() failed to set mono recording mode");
398 }
399
400 // Restore recording if it was enabled already when calling this function.
401 if (isRecording)
402 {
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000403 if (!_shared->ext_recording())
niklase@google.com470e71d2011-07-07 08:21:25 +0000404 {
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000405 WEBRTC_TRACE(kTraceInfo, kTraceVoice,
406 VoEId(_shared->instance_id(), -1),
407 "SetRecordingDevice() recording is now being restored...");
408 if (_shared->audio_device()->InitRecording() != 0)
niklase@google.com470e71d2011-07-07 08:21:25 +0000409 {
410 WEBRTC_TRACE(kTraceError, kTraceVoice,
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000411 VoEId(_shared->instance_id(), -1),
412 "SetRecordingDevice() failed to initialize recording");
niklase@google.com470e71d2011-07-07 08:21:25 +0000413 return -1;
414 }
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000415 if (_shared->audio_device()->StartRecording() != 0)
niklase@google.com470e71d2011-07-07 08:21:25 +0000416 {
417 WEBRTC_TRACE(kTraceError, kTraceVoice,
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000418 VoEId(_shared->instance_id(), -1),
niklase@google.com470e71d2011-07-07 08:21:25 +0000419 "SetRecordingDevice() failed to start recording");
420 return -1;
421 }
422 }
423 }
424
425 return 0;
426}
427
428int VoEHardwareImpl::SetPlayoutDevice(int index)
429{
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000430 WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
niklase@google.com470e71d2011-07-07 08:21:25 +0000431 "SetPlayoutDevice(index=%d)", index);
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000432 CriticalSectionScoped cs(_shared->crit_sec());
niklase@google.com470e71d2011-07-07 08:21:25 +0000433
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000434 if (!_shared->statistics().Initialized())
niklase@google.com470e71d2011-07-07 08:21:25 +0000435 {
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000436 _shared->SetLastError(VE_NOT_INITED, kTraceError);
niklase@google.com470e71d2011-07-07 08:21:25 +0000437 return -1;
438 }
439
440 bool isPlaying(false);
441
442 // Store state about activated playout to be able to restore it after the
443 // playout device has been modified.
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000444 if (_shared->audio_device()->Playing())
niklase@google.com470e71d2011-07-07 08:21:25 +0000445 {
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000446 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_shared->instance_id(), -1),
niklase@google.com470e71d2011-07-07 08:21:25 +0000447 "SetPlayoutDevice() device is modified while playout is "
448 "active...");
449 isPlaying = true;
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000450 if (_shared->audio_device()->StopPlayout() == -1)
niklase@google.com470e71d2011-07-07 08:21:25 +0000451 {
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000452 _shared->SetLastError(VE_AUDIO_DEVICE_MODULE_ERROR, kTraceError,
niklase@google.com470e71d2011-07-07 08:21:25 +0000453 "SetPlayoutDevice() unable to stop playout");
454 return -1;
455 }
456 }
457
458 // We let the module do the index sanity
459
460 // Map indices to unsigned since underlying functions need that
pbos@webrtc.org6141e132013-04-09 10:09:10 +0000461 uint16_t indexU = static_cast<uint16_t> (index);
niklase@google.com470e71d2011-07-07 08:21:25 +0000462
pbos@webrtc.org6141e132013-04-09 10:09:10 +0000463 int32_t res(0);
niklase@google.com470e71d2011-07-07 08:21:25 +0000464
465 if (index == -1)
466 {
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000467 res = _shared->audio_device()->SetPlayoutDevice(
niklase@google.com470e71d2011-07-07 08:21:25 +0000468 AudioDeviceModule::kDefaultCommunicationDevice);
469 }
470 else if (index == -2)
471 {
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000472 res = _shared->audio_device()->SetPlayoutDevice(
niklase@google.com470e71d2011-07-07 08:21:25 +0000473 AudioDeviceModule::kDefaultDevice);
474 }
475 else
476 {
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000477 res = _shared->audio_device()->SetPlayoutDevice(indexU);
niklase@google.com470e71d2011-07-07 08:21:25 +0000478 }
479
480 if (res != 0)
481 {
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000482 _shared->SetLastError(VE_SOUNDCARD_ERROR, kTraceError,
niklase@google.com470e71d2011-07-07 08:21:25 +0000483 "SetPlayoutDevice() unable to set the playout device");
484 return -1;
485 }
486
487 // Init speaker, so user can do volume settings etc
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000488 if (_shared->audio_device()->InitSpeaker() == -1)
niklase@google.com470e71d2011-07-07 08:21:25 +0000489 {
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000490 _shared->SetLastError(VE_CANNOT_ACCESS_SPEAKER_VOL, kTraceWarning,
niklase@google.com470e71d2011-07-07 08:21:25 +0000491 "SetPlayoutDevice() cannot access speaker");
492 }
493
494 // Set number of channels
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000495 bool available = false;
496 _shared->audio_device()->StereoPlayoutIsAvailable(&available);
497 if (_shared->audio_device()->SetStereoPlayout(available) != 0)
niklase@google.com470e71d2011-07-07 08:21:25 +0000498 {
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000499 _shared->SetLastError(VE_SOUNDCARD_ERROR, kTraceWarning,
niklase@google.com470e71d2011-07-07 08:21:25 +0000500 "SetPlayoutDevice() failed to set stereo playout mode");
501 }
502
503 // Restore playout if it was enabled already when calling this function.
504 if (isPlaying)
505 {
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000506 if (!_shared->ext_playout())
niklase@google.com470e71d2011-07-07 08:21:25 +0000507 {
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000508 WEBRTC_TRACE(kTraceInfo, kTraceVoice,
509 VoEId(_shared->instance_id(), -1),
510 "SetPlayoutDevice() playout is now being restored...");
511 if (_shared->audio_device()->InitPlayout() != 0)
niklase@google.com470e71d2011-07-07 08:21:25 +0000512 {
513 WEBRTC_TRACE(kTraceError, kTraceVoice,
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000514 VoEId(_shared->instance_id(), -1),
515 "SetPlayoutDevice() failed to initialize playout");
niklase@google.com470e71d2011-07-07 08:21:25 +0000516 return -1;
517 }
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000518 if (_shared->audio_device()->StartPlayout() != 0)
niklase@google.com470e71d2011-07-07 08:21:25 +0000519 {
520 WEBRTC_TRACE(kTraceError, kTraceVoice,
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000521 VoEId(_shared->instance_id(), -1),
niklase@google.com470e71d2011-07-07 08:21:25 +0000522 "SetPlayoutDevice() failed to start playout");
523 return -1;
524 }
525 }
526 }
527
528 return 0;
529}
530
leozwang@webrtc.org96bcac82012-12-04 19:11:55 +0000531int VoEHardwareImpl::SetRecordingSampleRate(unsigned int samples_per_sec) {
532 WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
533 "%s", __FUNCTION__);
534 if (!_shared->statistics().Initialized()) {
535 _shared->SetLastError(VE_NOT_INITED, kTraceError);
536 return false;
537 }
538 return _shared->audio_device()->SetRecordingSampleRate(samples_per_sec);
539}
540
541int VoEHardwareImpl::RecordingSampleRate(unsigned int* samples_per_sec) const {
542 WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
543 "%s", __FUNCTION__);
544 if (!_shared->statistics().Initialized()) {
545 _shared->SetLastError(VE_NOT_INITED, kTraceError);
546 return false;
547 }
548 return _shared->audio_device()->RecordingSampleRate(samples_per_sec);
549}
550
551int VoEHardwareImpl::SetPlayoutSampleRate(unsigned int samples_per_sec) {
552 WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
553 "%s", __FUNCTION__);
554 if (!_shared->statistics().Initialized()) {
555 _shared->SetLastError(VE_NOT_INITED, kTraceError);
556 return false;
557 }
558 return _shared->audio_device()->SetPlayoutSampleRate(samples_per_sec);
559}
560
561int VoEHardwareImpl::PlayoutSampleRate(unsigned int* samples_per_sec) const {
562 WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
563 "%s", __FUNCTION__);
564 if (!_shared->statistics().Initialized()) {
565 _shared->SetLastError(VE_NOT_INITED, kTraceError);
566 return false;
567 }
568 return _shared->audio_device()->PlayoutSampleRate(samples_per_sec);
569}
570
niklase@google.com470e71d2011-07-07 08:21:25 +0000571#endif // WEBRTC_VOICE_ENGINE_HARDWARE_API
572
pbos@webrtc.orgd900e8b2013-07-03 15:12:26 +0000573} // namespace webrtc