blob: 3d8a7a832dd17fbc2943ceb0d23c50bad55a0aaf [file] [log] [blame]
niklase@google.com470e71d2011-07-07 08:21:25 +00001/*
xians@webrtc.org3ab6dda2012-02-16 18:15:54 +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_volume_control_impl.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000012
pbos@webrtc.org956aa7e2013-05-21 13:52:32 +000013#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
14#include "webrtc/system_wrappers/interface/trace.h"
15#include "webrtc/voice_engine/channel.h"
16#include "webrtc/voice_engine/include/voe_errors.h"
17#include "webrtc/voice_engine/output_mixer.h"
18#include "webrtc/voice_engine/transmit_mixer.h"
19#include "webrtc/voice_engine/voice_engine_impl.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000020
21namespace webrtc {
22
Jelena Marusic0d266052015-05-04 14:15:32 +020023VoEVolumeControl* VoEVolumeControl::GetInterface(VoiceEngine* voiceEngine) {
niklase@google.com470e71d2011-07-07 08:21:25 +000024#ifndef WEBRTC_VOICE_ENGINE_VOLUME_CONTROL_API
Jelena Marusic0d266052015-05-04 14:15:32 +020025 return NULL;
niklase@google.com470e71d2011-07-07 08:21:25 +000026#else
Jelena Marusic0d266052015-05-04 14:15:32 +020027 if (NULL == voiceEngine) {
28 return NULL;
29 }
30 VoiceEngineImpl* s = static_cast<VoiceEngineImpl*>(voiceEngine);
31 s->AddRef();
32 return s;
niklase@google.com470e71d2011-07-07 08:21:25 +000033#endif
34}
35
36#ifdef WEBRTC_VOICE_ENGINE_VOLUME_CONTROL_API
37
tommi@webrtc.org851becd2012-04-04 14:57:19 +000038VoEVolumeControlImpl::VoEVolumeControlImpl(voe::SharedData* shared)
Jelena Marusic0d266052015-05-04 14:15:32 +020039 : _shared(shared) {
40 WEBRTC_TRACE(kTraceMemory, kTraceVoice, VoEId(_shared->instance_id(), -1),
niklase@google.com470e71d2011-07-07 08:21:25 +000041 "VoEVolumeControlImpl::VoEVolumeControlImpl() - ctor");
42}
43
Jelena Marusic0d266052015-05-04 14:15:32 +020044VoEVolumeControlImpl::~VoEVolumeControlImpl() {
45 WEBRTC_TRACE(kTraceMemory, kTraceVoice, VoEId(_shared->instance_id(), -1),
niklase@google.com470e71d2011-07-07 08:21:25 +000046 "VoEVolumeControlImpl::~VoEVolumeControlImpl() - dtor");
47}
48
Jelena Marusic0d266052015-05-04 14:15:32 +020049int VoEVolumeControlImpl::SetSpeakerVolume(unsigned int volume) {
50 WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
niklase@google.com470e71d2011-07-07 08:21:25 +000051 "SetSpeakerVolume(volume=%u)", volume);
niklase@google.com470e71d2011-07-07 08:21:25 +000052
Jelena Marusic0d266052015-05-04 14:15:32 +020053 if (!_shared->statistics().Initialized()) {
54 _shared->SetLastError(VE_NOT_INITED, kTraceError);
55 return -1;
56 }
57 if (volume > kMaxVolumeLevel) {
58 _shared->SetLastError(VE_INVALID_ARGUMENT, kTraceError,
59 "SetSpeakerVolume() invalid argument");
60 return -1;
61 }
niklase@google.com470e71d2011-07-07 08:21:25 +000062
Jelena Marusic0d266052015-05-04 14:15:32 +020063 uint32_t maxVol(0);
64 uint32_t spkrVol(0);
niklase@google.com470e71d2011-07-07 08:21:25 +000065
Jelena Marusic0d266052015-05-04 14:15:32 +020066 // scale: [0,kMaxVolumeLevel] -> [0,MaxSpeakerVolume]
67 if (_shared->audio_device()->MaxSpeakerVolume(&maxVol) != 0) {
68 _shared->SetLastError(VE_MIC_VOL_ERROR, kTraceError,
69 "SetSpeakerVolume() failed to get max volume");
70 return -1;
71 }
72 // Round the value and avoid floating computation.
73 spkrVol = (uint32_t)((volume * maxVol + (int)(kMaxVolumeLevel / 2)) /
74 (kMaxVolumeLevel));
niklase@google.com470e71d2011-07-07 08:21:25 +000075
Jelena Marusic0d266052015-05-04 14:15:32 +020076 // set the actual volume using the audio mixer
77 if (_shared->audio_device()->SetSpeakerVolume(spkrVol) != 0) {
78 _shared->SetLastError(VE_MIC_VOL_ERROR, kTraceError,
79 "SetSpeakerVolume() failed to set speaker volume");
80 return -1;
81 }
82 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +000083}
84
Jelena Marusic0d266052015-05-04 14:15:32 +020085int VoEVolumeControlImpl::GetSpeakerVolume(unsigned int& volume) {
86 WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
niklase@google.com470e71d2011-07-07 08:21:25 +000087 "GetSpeakerVolume()");
niklase@google.com470e71d2011-07-07 08:21:25 +000088
Jelena Marusic0d266052015-05-04 14:15:32 +020089 if (!_shared->statistics().Initialized()) {
90 _shared->SetLastError(VE_NOT_INITED, kTraceError);
91 return -1;
92 }
niklase@google.com470e71d2011-07-07 08:21:25 +000093
Jelena Marusic0d266052015-05-04 14:15:32 +020094 uint32_t spkrVol(0);
95 uint32_t maxVol(0);
niklase@google.com470e71d2011-07-07 08:21:25 +000096
Jelena Marusic0d266052015-05-04 14:15:32 +020097 if (_shared->audio_device()->SpeakerVolume(&spkrVol) != 0) {
98 _shared->SetLastError(VE_GET_MIC_VOL_ERROR, kTraceError,
99 "GetSpeakerVolume() unable to get speaker volume");
100 return -1;
101 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000102
Jelena Marusic0d266052015-05-04 14:15:32 +0200103 // scale: [0, MaxSpeakerVolume] -> [0, kMaxVolumeLevel]
104 if (_shared->audio_device()->MaxSpeakerVolume(&maxVol) != 0) {
105 _shared->SetLastError(
106 VE_GET_MIC_VOL_ERROR, kTraceError,
107 "GetSpeakerVolume() unable to get max speaker volume");
108 return -1;
109 }
110 // Round the value and avoid floating computation.
111 volume =
112 (uint32_t)((spkrVol * kMaxVolumeLevel + (int)(maxVol / 2)) / (maxVol));
niklase@google.com470e71d2011-07-07 08:21:25 +0000113
Jelena Marusic0d266052015-05-04 14:15:32 +0200114 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, VoEId(_shared->instance_id(), -1),
115 "GetSpeakerVolume() => volume=%d", volume);
116 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000117}
118
Jelena Marusic0d266052015-05-04 14:15:32 +0200119int VoEVolumeControlImpl::SetMicVolume(unsigned int volume) {
120 WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
niklase@google.com470e71d2011-07-07 08:21:25 +0000121 "SetMicVolume(volume=%u)", volume);
niklase@google.com470e71d2011-07-07 08:21:25 +0000122
Jelena Marusic0d266052015-05-04 14:15:32 +0200123 if (!_shared->statistics().Initialized()) {
124 _shared->SetLastError(VE_NOT_INITED, kTraceError);
125 return -1;
126 }
127 if (volume > kMaxVolumeLevel) {
128 _shared->SetLastError(VE_INVALID_ARGUMENT, kTraceError,
129 "SetMicVolume() invalid argument");
130 return -1;
131 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000132
Jelena Marusic0d266052015-05-04 14:15:32 +0200133 uint32_t maxVol(0);
134 uint32_t micVol(0);
niklase@google.com470e71d2011-07-07 08:21:25 +0000135
Jelena Marusic0d266052015-05-04 14:15:32 +0200136 // scale: [0, kMaxVolumeLevel] -> [0,MaxMicrophoneVolume]
137 if (_shared->audio_device()->MaxMicrophoneVolume(&maxVol) != 0) {
138 _shared->SetLastError(VE_MIC_VOL_ERROR, kTraceError,
139 "SetMicVolume() failed to get max volume");
140 return -1;
141 }
142
143 if (volume == kMaxVolumeLevel) {
144 // On Linux running pulse, users are able to set the volume above 100%
145 // through the volume control panel, where the +100% range is digital
146 // scaling. WebRTC does not support setting the volume above 100%, and
147 // simply ignores changing the volume if the user tries to set it to
148 // |kMaxVolumeLevel| while the current volume is higher than |maxVol|.
149 if (_shared->audio_device()->MicrophoneVolume(&micVol) != 0) {
150 _shared->SetLastError(VE_GET_MIC_VOL_ERROR, kTraceError,
151 "SetMicVolume() unable to get microphone volume");
152 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +0000153 }
Jelena Marusic0d266052015-05-04 14:15:32 +0200154 if (micVol >= maxVol)
155 return 0;
156 }
xians@webrtc.org3ab6dda2012-02-16 18:15:54 +0000157
Jelena Marusic0d266052015-05-04 14:15:32 +0200158 // Round the value and avoid floating point computation.
159 micVol = (uint32_t)((volume * maxVol + (int)(kMaxVolumeLevel / 2)) /
160 (kMaxVolumeLevel));
xians@webrtc.org3ab6dda2012-02-16 18:15:54 +0000161
Jelena Marusic0d266052015-05-04 14:15:32 +0200162 // set the actual volume using the audio mixer
163 if (_shared->audio_device()->SetMicrophoneVolume(micVol) != 0) {
164 _shared->SetLastError(VE_MIC_VOL_ERROR, kTraceError,
165 "SetMicVolume() failed to set mic volume");
166 return -1;
167 }
168 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000169}
170
Jelena Marusic0d266052015-05-04 14:15:32 +0200171int VoEVolumeControlImpl::GetMicVolume(unsigned int& volume) {
172 WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
niklase@google.com470e71d2011-07-07 08:21:25 +0000173 "GetMicVolume()");
niklase@google.com470e71d2011-07-07 08:21:25 +0000174
Jelena Marusic0d266052015-05-04 14:15:32 +0200175 if (!_shared->statistics().Initialized()) {
176 _shared->SetLastError(VE_NOT_INITED, kTraceError);
177 return -1;
178 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000179
Jelena Marusic0d266052015-05-04 14:15:32 +0200180 uint32_t micVol(0);
181 uint32_t maxVol(0);
niklase@google.com470e71d2011-07-07 08:21:25 +0000182
Jelena Marusic0d266052015-05-04 14:15:32 +0200183 if (_shared->audio_device()->MicrophoneVolume(&micVol) != 0) {
184 _shared->SetLastError(VE_GET_MIC_VOL_ERROR, kTraceError,
185 "GetMicVolume() unable to get microphone volume");
186 return -1;
187 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000188
Jelena Marusic0d266052015-05-04 14:15:32 +0200189 // scale: [0, MaxMicrophoneVolume] -> [0, kMaxVolumeLevel]
190 if (_shared->audio_device()->MaxMicrophoneVolume(&maxVol) != 0) {
191 _shared->SetLastError(VE_GET_MIC_VOL_ERROR, kTraceError,
192 "GetMicVolume() unable to get max microphone volume");
193 return -1;
194 }
195 if (micVol < maxVol) {
196 // Round the value and avoid floating point calculation.
197 volume =
198 (uint32_t)((micVol * kMaxVolumeLevel + (int)(maxVol / 2)) / (maxVol));
199 } else {
200 // Truncate the value to the kMaxVolumeLevel.
201 volume = kMaxVolumeLevel;
202 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000203
Jelena Marusic0d266052015-05-04 14:15:32 +0200204 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, VoEId(_shared->instance_id(), -1),
205 "GetMicVolume() => volume=%d", volume);
206 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000207}
208
Jelena Marusic0d266052015-05-04 14:15:32 +0200209int VoEVolumeControlImpl::SetInputMute(int channel, bool enable) {
210 WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
niklase@google.com470e71d2011-07-07 08:21:25 +0000211 "SetInputMute(channel=%d, enable=%d)", channel, enable);
212
Jelena Marusic0d266052015-05-04 14:15:32 +0200213 if (!_shared->statistics().Initialized()) {
214 _shared->SetLastError(VE_NOT_INITED, kTraceError);
215 return -1;
216 }
217 if (channel == -1) {
218 // Mute before demultiplexing <=> affects all channels
219 return _shared->transmit_mixer()->SetMute(enable);
220 }
221 // Mute after demultiplexing <=> affects one channel only
222 voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
223 voe::Channel* channelPtr = ch.channel();
224 if (channelPtr == NULL) {
225 _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
226 "SetInputMute() failed to locate channel");
227 return -1;
228 }
229 return channelPtr->SetMute(enable);
niklase@google.com470e71d2011-07-07 08:21:25 +0000230}
231
Jelena Marusic0d266052015-05-04 14:15:32 +0200232int VoEVolumeControlImpl::GetInputMute(int channel, bool& enabled) {
233 WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
niklase@google.com470e71d2011-07-07 08:21:25 +0000234 "GetInputMute(channel=%d)", channel);
235
Jelena Marusic0d266052015-05-04 14:15:32 +0200236 if (!_shared->statistics().Initialized()) {
237 _shared->SetLastError(VE_NOT_INITED, kTraceError);
238 return -1;
239 }
240 if (channel == -1) {
241 enabled = _shared->transmit_mixer()->Mute();
242 } else {
243 voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
244 voe::Channel* channelPtr = ch.channel();
245 if (channelPtr == NULL) {
246 _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
247 "SetInputMute() failed to locate channel");
248 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +0000249 }
Jelena Marusic0d266052015-05-04 14:15:32 +0200250 enabled = channelPtr->Mute();
251 }
252 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, VoEId(_shared->instance_id(), -1),
253 "GetInputMute() => enabled = %d", (int)enabled);
254 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000255}
256
Jelena Marusic0d266052015-05-04 14:15:32 +0200257int VoEVolumeControlImpl::GetSpeechInputLevel(unsigned int& level) {
258 WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
niklase@google.com470e71d2011-07-07 08:21:25 +0000259 "GetSpeechInputLevel()");
zakkhoyt@google.com630504f2011-07-13 20:06:58 +0000260
Jelena Marusic0d266052015-05-04 14:15:32 +0200261 if (!_shared->statistics().Initialized()) {
262 _shared->SetLastError(VE_NOT_INITED, kTraceError);
263 return -1;
264 }
265 int8_t currentLevel = _shared->transmit_mixer()->AudioLevel();
266 level = static_cast<unsigned int>(currentLevel);
267 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, VoEId(_shared->instance_id(), -1),
268 "GetSpeechInputLevel() => %d", level);
269 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000270}
271
272int VoEVolumeControlImpl::GetSpeechOutputLevel(int channel,
Jelena Marusic0d266052015-05-04 14:15:32 +0200273 unsigned int& level) {
274 WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
zakkhoyt@google.com630504f2011-07-13 20:06:58 +0000275 "GetSpeechOutputLevel(channel=%d, level=?)", channel);
henrika@webrtc.orgf383a1b2014-05-14 11:51:45 +0000276
Jelena Marusic0d266052015-05-04 14:15:32 +0200277 if (!_shared->statistics().Initialized()) {
278 _shared->SetLastError(VE_NOT_INITED, kTraceError);
279 return -1;
280 }
281 if (channel == -1) {
282 return _shared->output_mixer()->GetSpeechOutputLevel((uint32_t&)level);
283 } else {
284 voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
285 voe::Channel* channelPtr = ch.channel();
286 if (channelPtr == NULL) {
287 _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
288 "GetSpeechOutputLevel() failed to locate channel");
289 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +0000290 }
Jelena Marusic0d266052015-05-04 14:15:32 +0200291 channelPtr->GetSpeechOutputLevel((uint32_t&)level);
292 }
293 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000294}
295
Jelena Marusic0d266052015-05-04 14:15:32 +0200296int VoEVolumeControlImpl::GetSpeechInputLevelFullRange(unsigned int& level) {
297 WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
niklase@google.com470e71d2011-07-07 08:21:25 +0000298 "GetSpeechInputLevelFullRange(level=?)");
zakkhoyt@google.com5e266632011-07-15 18:21:34 +0000299
Jelena Marusic0d266052015-05-04 14:15:32 +0200300 if (!_shared->statistics().Initialized()) {
301 _shared->SetLastError(VE_NOT_INITED, kTraceError);
302 return -1;
303 }
304 int16_t currentLevel = _shared->transmit_mixer()->AudioLevelFullRange();
305 level = static_cast<unsigned int>(currentLevel);
306 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, VoEId(_shared->instance_id(), -1),
307 "GetSpeechInputLevelFullRange() => %d", level);
308 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000309}
310
311int VoEVolumeControlImpl::GetSpeechOutputLevelFullRange(int channel,
Jelena Marusic0d266052015-05-04 14:15:32 +0200312 unsigned int& level) {
313 WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
niklase@google.com470e71d2011-07-07 08:21:25 +0000314 "GetSpeechOutputLevelFullRange(channel=%d, level=?)", channel);
zakkhoyt@google.com5e266632011-07-15 18:21:34 +0000315
Jelena Marusic0d266052015-05-04 14:15:32 +0200316 if (!_shared->statistics().Initialized()) {
317 _shared->SetLastError(VE_NOT_INITED, kTraceError);
318 return -1;
319 }
320 if (channel == -1) {
321 return _shared->output_mixer()->GetSpeechOutputLevelFullRange(
322 (uint32_t&)level);
323 } else {
324 voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
325 voe::Channel* channelPtr = ch.channel();
326 if (channelPtr == NULL) {
327 _shared->SetLastError(
328 VE_CHANNEL_NOT_VALID, kTraceError,
329 "GetSpeechOutputLevelFullRange() failed to locate channel");
330 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +0000331 }
Jelena Marusic0d266052015-05-04 14:15:32 +0200332 channelPtr->GetSpeechOutputLevelFullRange((uint32_t&)level);
333 }
334 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000335}
336
337int VoEVolumeControlImpl::SetChannelOutputVolumeScaling(int channel,
Jelena Marusic0d266052015-05-04 14:15:32 +0200338 float scaling) {
339 WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
niklase@google.com470e71d2011-07-07 08:21:25 +0000340 "SetChannelOutputVolumeScaling(channel=%d, scaling=%3.2f)",
341 channel, scaling);
Jelena Marusic0d266052015-05-04 14:15:32 +0200342 if (!_shared->statistics().Initialized()) {
343 _shared->SetLastError(VE_NOT_INITED, kTraceError);
344 return -1;
345 }
346 if (scaling < kMinOutputVolumeScaling || scaling > kMaxOutputVolumeScaling) {
347 _shared->SetLastError(VE_INVALID_ARGUMENT, kTraceError,
348 "SetChannelOutputVolumeScaling() invalid parameter");
349 return -1;
350 }
351 voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
352 voe::Channel* channelPtr = ch.channel();
353 if (channelPtr == NULL) {
354 _shared->SetLastError(
355 VE_CHANNEL_NOT_VALID, kTraceError,
356 "SetChannelOutputVolumeScaling() failed to locate channel");
357 return -1;
358 }
359 return channelPtr->SetChannelOutputVolumeScaling(scaling);
niklase@google.com470e71d2011-07-07 08:21:25 +0000360}
361
362int VoEVolumeControlImpl::GetChannelOutputVolumeScaling(int channel,
Jelena Marusic0d266052015-05-04 14:15:32 +0200363 float& scaling) {
364 WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
niklase@google.com470e71d2011-07-07 08:21:25 +0000365 "GetChannelOutputVolumeScaling(channel=%d, scaling=?)", channel);
Jelena Marusic0d266052015-05-04 14:15:32 +0200366 if (!_shared->statistics().Initialized()) {
367 _shared->SetLastError(VE_NOT_INITED, kTraceError);
368 return -1;
369 }
370 voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
371 voe::Channel* channelPtr = ch.channel();
372 if (channelPtr == NULL) {
373 _shared->SetLastError(
374 VE_CHANNEL_NOT_VALID, kTraceError,
375 "GetChannelOutputVolumeScaling() failed to locate channel");
376 return -1;
377 }
378 return channelPtr->GetChannelOutputVolumeScaling(scaling);
niklase@google.com470e71d2011-07-07 08:21:25 +0000379}
380
381int VoEVolumeControlImpl::SetOutputVolumePan(int channel,
382 float left,
Jelena Marusic0d266052015-05-04 14:15:32 +0200383 float right) {
384 WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
niklase@google.com470e71d2011-07-07 08:21:25 +0000385 "SetOutputVolumePan(channel=%d, left=%2.1f, right=%2.1f)",
386 channel, left, right);
niklase@google.com470e71d2011-07-07 08:21:25 +0000387
Jelena Marusic0d266052015-05-04 14:15:32 +0200388 if (!_shared->statistics().Initialized()) {
389 _shared->SetLastError(VE_NOT_INITED, kTraceError);
390 return -1;
391 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000392
Jelena Marusic0d266052015-05-04 14:15:32 +0200393 bool available(false);
394 _shared->audio_device()->StereoPlayoutIsAvailable(&available);
395 if (!available) {
396 _shared->SetLastError(VE_FUNC_NO_STEREO, kTraceError,
397 "SetOutputVolumePan() stereo playout not supported");
398 return -1;
399 }
400 if ((left < kMinOutputVolumePanning) || (left > kMaxOutputVolumePanning) ||
401 (right < kMinOutputVolumePanning) || (right > kMaxOutputVolumePanning)) {
402 _shared->SetLastError(VE_INVALID_ARGUMENT, kTraceError,
403 "SetOutputVolumePan() invalid parameter");
404 return -1;
405 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000406
Jelena Marusic0d266052015-05-04 14:15:32 +0200407 if (channel == -1) {
408 // Master balance (affectes the signal after output mixing)
409 return _shared->output_mixer()->SetOutputVolumePan(left, right);
410 }
411 // Per-channel balance (affects the signal before output mixing)
412 voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
413 voe::Channel* channelPtr = ch.channel();
414 if (channelPtr == NULL) {
415 _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
416 "SetOutputVolumePan() failed to locate channel");
417 return -1;
418 }
419 return channelPtr->SetOutputVolumePan(left, right);
niklase@google.com470e71d2011-07-07 08:21:25 +0000420}
421
422int VoEVolumeControlImpl::GetOutputVolumePan(int channel,
423 float& left,
Jelena Marusic0d266052015-05-04 14:15:32 +0200424 float& right) {
425 WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
niklase@google.com470e71d2011-07-07 08:21:25 +0000426 "GetOutputVolumePan(channel=%d, left=?, right=?)", channel);
niklase@google.com470e71d2011-07-07 08:21:25 +0000427
Jelena Marusic0d266052015-05-04 14:15:32 +0200428 if (!_shared->statistics().Initialized()) {
429 _shared->SetLastError(VE_NOT_INITED, kTraceError);
430 return -1;
431 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000432
Jelena Marusic0d266052015-05-04 14:15:32 +0200433 bool available(false);
434 _shared->audio_device()->StereoPlayoutIsAvailable(&available);
435 if (!available) {
436 _shared->SetLastError(VE_FUNC_NO_STEREO, kTraceError,
437 "GetOutputVolumePan() stereo playout not supported");
438 return -1;
439 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000440
Jelena Marusic0d266052015-05-04 14:15:32 +0200441 if (channel == -1) {
442 return _shared->output_mixer()->GetOutputVolumePan(left, right);
443 }
444 voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
445 voe::Channel* channelPtr = ch.channel();
446 if (channelPtr == NULL) {
447 _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
448 "GetOutputVolumePan() failed to locate channel");
449 return -1;
450 }
451 return channelPtr->GetOutputVolumePan(left, right);
niklase@google.com470e71d2011-07-07 08:21:25 +0000452}
453
454#endif // #ifdef WEBRTC_VOICE_ENGINE_VOLUME_CONTROL_API
455
456} // namespace webrtc