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