blob: eb17db3219baca15497c5ec13be065694fafa6d3 [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
Henrik Kjellander98f53512015-10-28 18:17:40 +010013#include "webrtc/system_wrappers/include/trace.h"
pbos@webrtc.org956aa7e2013-05-21 13:52:32 +000014#include "webrtc/voice_engine/channel.h"
15#include "webrtc/voice_engine/include/voe_errors.h"
16#include "webrtc/voice_engine/output_mixer.h"
17#include "webrtc/voice_engine/transmit_mixer.h"
18#include "webrtc/voice_engine/voice_engine_impl.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000019
20namespace webrtc {
21
Jelena Marusic0d266052015-05-04 14:15:32 +020022VoEVolumeControl* VoEVolumeControl::GetInterface(VoiceEngine* voiceEngine) {
niklase@google.com470e71d2011-07-07 08:21:25 +000023#ifndef WEBRTC_VOICE_ENGINE_VOLUME_CONTROL_API
Jelena Marusic0d266052015-05-04 14:15:32 +020024 return NULL;
niklase@google.com470e71d2011-07-07 08:21:25 +000025#else
Jelena Marusic0d266052015-05-04 14:15:32 +020026 if (NULL == voiceEngine) {
27 return NULL;
28 }
29 VoiceEngineImpl* s = static_cast<VoiceEngineImpl*>(voiceEngine);
30 s->AddRef();
31 return s;
niklase@google.com470e71d2011-07-07 08:21:25 +000032#endif
33}
34
35#ifdef WEBRTC_VOICE_ENGINE_VOLUME_CONTROL_API
36
tommi@webrtc.org851becd2012-04-04 14:57:19 +000037VoEVolumeControlImpl::VoEVolumeControlImpl(voe::SharedData* shared)
Jelena Marusic0d266052015-05-04 14:15:32 +020038 : _shared(shared) {
39 WEBRTC_TRACE(kTraceMemory, kTraceVoice, VoEId(_shared->instance_id(), -1),
niklase@google.com470e71d2011-07-07 08:21:25 +000040 "VoEVolumeControlImpl::VoEVolumeControlImpl() - ctor");
41}
42
Jelena Marusic0d266052015-05-04 14:15:32 +020043VoEVolumeControlImpl::~VoEVolumeControlImpl() {
44 WEBRTC_TRACE(kTraceMemory, kTraceVoice, VoEId(_shared->instance_id(), -1),
niklase@google.com470e71d2011-07-07 08:21:25 +000045 "VoEVolumeControlImpl::~VoEVolumeControlImpl() - dtor");
46}
47
Jelena Marusic0d266052015-05-04 14:15:32 +020048int VoEVolumeControlImpl::SetSpeakerVolume(unsigned int volume) {
49 WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
niklase@google.com470e71d2011-07-07 08:21:25 +000050 "SetSpeakerVolume(volume=%u)", volume);
niklase@google.com470e71d2011-07-07 08:21:25 +000051
Jelena Marusic0d266052015-05-04 14:15:32 +020052 if (!_shared->statistics().Initialized()) {
53 _shared->SetLastError(VE_NOT_INITED, kTraceError);
54 return -1;
55 }
56 if (volume > kMaxVolumeLevel) {
57 _shared->SetLastError(VE_INVALID_ARGUMENT, kTraceError,
58 "SetSpeakerVolume() invalid argument");
59 return -1;
60 }
niklase@google.com470e71d2011-07-07 08:21:25 +000061
Jelena Marusic0d266052015-05-04 14:15:32 +020062 uint32_t maxVol(0);
63 uint32_t spkrVol(0);
niklase@google.com470e71d2011-07-07 08:21:25 +000064
Jelena Marusic0d266052015-05-04 14:15:32 +020065 // scale: [0,kMaxVolumeLevel] -> [0,MaxSpeakerVolume]
66 if (_shared->audio_device()->MaxSpeakerVolume(&maxVol) != 0) {
67 _shared->SetLastError(VE_MIC_VOL_ERROR, kTraceError,
68 "SetSpeakerVolume() failed to get max volume");
69 return -1;
70 }
71 // Round the value and avoid floating computation.
72 spkrVol = (uint32_t)((volume * maxVol + (int)(kMaxVolumeLevel / 2)) /
73 (kMaxVolumeLevel));
niklase@google.com470e71d2011-07-07 08:21:25 +000074
Jelena Marusic0d266052015-05-04 14:15:32 +020075 // set the actual volume using the audio mixer
76 if (_shared->audio_device()->SetSpeakerVolume(spkrVol) != 0) {
77 _shared->SetLastError(VE_MIC_VOL_ERROR, kTraceError,
78 "SetSpeakerVolume() failed to set speaker volume");
79 return -1;
80 }
81 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +000082}
83
Jelena Marusic0d266052015-05-04 14:15:32 +020084int VoEVolumeControlImpl::GetSpeakerVolume(unsigned int& volume) {
niklase@google.com470e71d2011-07-07 08:21:25 +000085
Jelena Marusic0d266052015-05-04 14:15:32 +020086 if (!_shared->statistics().Initialized()) {
87 _shared->SetLastError(VE_NOT_INITED, kTraceError);
88 return -1;
89 }
niklase@google.com470e71d2011-07-07 08:21:25 +000090
Jelena Marusic0d266052015-05-04 14:15:32 +020091 uint32_t spkrVol(0);
92 uint32_t maxVol(0);
niklase@google.com470e71d2011-07-07 08:21:25 +000093
Jelena Marusic0d266052015-05-04 14:15:32 +020094 if (_shared->audio_device()->SpeakerVolume(&spkrVol) != 0) {
95 _shared->SetLastError(VE_GET_MIC_VOL_ERROR, kTraceError,
96 "GetSpeakerVolume() unable to get speaker volume");
97 return -1;
98 }
niklase@google.com470e71d2011-07-07 08:21:25 +000099
Jelena Marusic0d266052015-05-04 14:15:32 +0200100 // scale: [0, MaxSpeakerVolume] -> [0, kMaxVolumeLevel]
101 if (_shared->audio_device()->MaxSpeakerVolume(&maxVol) != 0) {
102 _shared->SetLastError(
103 VE_GET_MIC_VOL_ERROR, kTraceError,
104 "GetSpeakerVolume() unable to get max speaker volume");
105 return -1;
106 }
107 // Round the value and avoid floating computation.
108 volume =
109 (uint32_t)((spkrVol * kMaxVolumeLevel + (int)(maxVol / 2)) / (maxVol));
niklase@google.com470e71d2011-07-07 08:21:25 +0000110
Jelena Marusic0d266052015-05-04 14:15:32 +0200111 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000112}
113
Jelena Marusic0d266052015-05-04 14:15:32 +0200114int VoEVolumeControlImpl::SetMicVolume(unsigned int volume) {
115 WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
niklase@google.com470e71d2011-07-07 08:21:25 +0000116 "SetMicVolume(volume=%u)", volume);
niklase@google.com470e71d2011-07-07 08:21:25 +0000117
Jelena Marusic0d266052015-05-04 14:15:32 +0200118 if (!_shared->statistics().Initialized()) {
119 _shared->SetLastError(VE_NOT_INITED, kTraceError);
120 return -1;
121 }
122 if (volume > kMaxVolumeLevel) {
123 _shared->SetLastError(VE_INVALID_ARGUMENT, kTraceError,
124 "SetMicVolume() invalid argument");
125 return -1;
126 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000127
Jelena Marusic0d266052015-05-04 14:15:32 +0200128 uint32_t maxVol(0);
129 uint32_t micVol(0);
niklase@google.com470e71d2011-07-07 08:21:25 +0000130
Jelena Marusic0d266052015-05-04 14:15:32 +0200131 // scale: [0, kMaxVolumeLevel] -> [0,MaxMicrophoneVolume]
132 if (_shared->audio_device()->MaxMicrophoneVolume(&maxVol) != 0) {
133 _shared->SetLastError(VE_MIC_VOL_ERROR, kTraceError,
134 "SetMicVolume() failed to get max volume");
135 return -1;
136 }
137
138 if (volume == kMaxVolumeLevel) {
139 // On Linux running pulse, users are able to set the volume above 100%
140 // through the volume control panel, where the +100% range is digital
141 // scaling. WebRTC does not support setting the volume above 100%, and
142 // simply ignores changing the volume if the user tries to set it to
143 // |kMaxVolumeLevel| while the current volume is higher than |maxVol|.
144 if (_shared->audio_device()->MicrophoneVolume(&micVol) != 0) {
145 _shared->SetLastError(VE_GET_MIC_VOL_ERROR, kTraceError,
146 "SetMicVolume() unable to get microphone volume");
147 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +0000148 }
Jelena Marusic0d266052015-05-04 14:15:32 +0200149 if (micVol >= maxVol)
150 return 0;
151 }
xians@webrtc.org3ab6dda2012-02-16 18:15:54 +0000152
Jelena Marusic0d266052015-05-04 14:15:32 +0200153 // Round the value and avoid floating point computation.
154 micVol = (uint32_t)((volume * maxVol + (int)(kMaxVolumeLevel / 2)) /
155 (kMaxVolumeLevel));
xians@webrtc.org3ab6dda2012-02-16 18:15:54 +0000156
Jelena Marusic0d266052015-05-04 14:15:32 +0200157 // set the actual volume using the audio mixer
158 if (_shared->audio_device()->SetMicrophoneVolume(micVol) != 0) {
159 _shared->SetLastError(VE_MIC_VOL_ERROR, kTraceError,
160 "SetMicVolume() failed to set mic volume");
161 return -1;
162 }
163 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000164}
165
Jelena Marusic0d266052015-05-04 14:15:32 +0200166int VoEVolumeControlImpl::GetMicVolume(unsigned int& volume) {
Jelena Marusic0d266052015-05-04 14:15:32 +0200167 if (!_shared->statistics().Initialized()) {
168 _shared->SetLastError(VE_NOT_INITED, kTraceError);
169 return -1;
170 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000171
Jelena Marusic0d266052015-05-04 14:15:32 +0200172 uint32_t micVol(0);
173 uint32_t maxVol(0);
niklase@google.com470e71d2011-07-07 08:21:25 +0000174
Jelena Marusic0d266052015-05-04 14:15:32 +0200175 if (_shared->audio_device()->MicrophoneVolume(&micVol) != 0) {
176 _shared->SetLastError(VE_GET_MIC_VOL_ERROR, kTraceError,
177 "GetMicVolume() unable to get microphone volume");
178 return -1;
179 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000180
Jelena Marusic0d266052015-05-04 14:15:32 +0200181 // scale: [0, MaxMicrophoneVolume] -> [0, kMaxVolumeLevel]
182 if (_shared->audio_device()->MaxMicrophoneVolume(&maxVol) != 0) {
183 _shared->SetLastError(VE_GET_MIC_VOL_ERROR, kTraceError,
184 "GetMicVolume() unable to get max microphone volume");
185 return -1;
186 }
187 if (micVol < maxVol) {
188 // Round the value and avoid floating point calculation.
189 volume =
190 (uint32_t)((micVol * kMaxVolumeLevel + (int)(maxVol / 2)) / (maxVol));
191 } else {
192 // Truncate the value to the kMaxVolumeLevel.
193 volume = kMaxVolumeLevel;
194 }
Jelena Marusic0d266052015-05-04 14:15:32 +0200195 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000196}
197
Jelena Marusic0d266052015-05-04 14:15:32 +0200198int VoEVolumeControlImpl::SetInputMute(int channel, bool enable) {
199 WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
niklase@google.com470e71d2011-07-07 08:21:25 +0000200 "SetInputMute(channel=%d, enable=%d)", channel, enable);
201
Jelena Marusic0d266052015-05-04 14:15:32 +0200202 if (!_shared->statistics().Initialized()) {
203 _shared->SetLastError(VE_NOT_INITED, kTraceError);
204 return -1;
205 }
206 if (channel == -1) {
207 // Mute before demultiplexing <=> affects all channels
208 return _shared->transmit_mixer()->SetMute(enable);
209 }
210 // Mute after demultiplexing <=> affects one channel only
211 voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
212 voe::Channel* channelPtr = ch.channel();
213 if (channelPtr == NULL) {
214 _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
215 "SetInputMute() failed to locate channel");
216 return -1;
217 }
solenberg1c2af8e2016-03-24 10:36:00 -0700218 return channelPtr->SetInputMute(enable);
niklase@google.com470e71d2011-07-07 08:21:25 +0000219}
220
Jelena Marusic0d266052015-05-04 14:15:32 +0200221int VoEVolumeControlImpl::GetInputMute(int channel, bool& enabled) {
Jelena Marusic0d266052015-05-04 14:15:32 +0200222 if (!_shared->statistics().Initialized()) {
223 _shared->SetLastError(VE_NOT_INITED, kTraceError);
224 return -1;
225 }
226 if (channel == -1) {
227 enabled = _shared->transmit_mixer()->Mute();
228 } else {
229 voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
230 voe::Channel* channelPtr = ch.channel();
231 if (channelPtr == NULL) {
232 _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
233 "SetInputMute() failed to locate channel");
234 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +0000235 }
solenberg1c2af8e2016-03-24 10:36:00 -0700236 enabled = channelPtr->InputMute();
Jelena Marusic0d266052015-05-04 14:15:32 +0200237 }
Jelena Marusic0d266052015-05-04 14:15:32 +0200238 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000239}
240
Jelena Marusic0d266052015-05-04 14:15:32 +0200241int VoEVolumeControlImpl::GetSpeechInputLevel(unsigned int& level) {
Jelena Marusic0d266052015-05-04 14:15:32 +0200242 if (!_shared->statistics().Initialized()) {
243 _shared->SetLastError(VE_NOT_INITED, kTraceError);
244 return -1;
245 }
246 int8_t currentLevel = _shared->transmit_mixer()->AudioLevel();
247 level = static_cast<unsigned int>(currentLevel);
Jelena Marusic0d266052015-05-04 14:15:32 +0200248 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000249}
250
251int VoEVolumeControlImpl::GetSpeechOutputLevel(int channel,
Jelena Marusic0d266052015-05-04 14:15:32 +0200252 unsigned int& level) {
Jelena Marusic0d266052015-05-04 14:15:32 +0200253 if (!_shared->statistics().Initialized()) {
254 _shared->SetLastError(VE_NOT_INITED, kTraceError);
255 return -1;
256 }
257 if (channel == -1) {
258 return _shared->output_mixer()->GetSpeechOutputLevel((uint32_t&)level);
259 } else {
260 voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
261 voe::Channel* channelPtr = ch.channel();
262 if (channelPtr == NULL) {
263 _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
264 "GetSpeechOutputLevel() failed to locate channel");
265 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +0000266 }
Jelena Marusic0d266052015-05-04 14:15:32 +0200267 channelPtr->GetSpeechOutputLevel((uint32_t&)level);
268 }
269 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000270}
271
Jelena Marusic0d266052015-05-04 14:15:32 +0200272int VoEVolumeControlImpl::GetSpeechInputLevelFullRange(unsigned int& level) {
Jelena Marusic0d266052015-05-04 14:15:32 +0200273 if (!_shared->statistics().Initialized()) {
274 _shared->SetLastError(VE_NOT_INITED, kTraceError);
275 return -1;
276 }
277 int16_t currentLevel = _shared->transmit_mixer()->AudioLevelFullRange();
278 level = static_cast<unsigned int>(currentLevel);
Jelena Marusic0d266052015-05-04 14:15:32 +0200279 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000280}
281
282int VoEVolumeControlImpl::GetSpeechOutputLevelFullRange(int channel,
Jelena Marusic0d266052015-05-04 14:15:32 +0200283 unsigned int& level) {
Jelena Marusic0d266052015-05-04 14:15:32 +0200284 if (!_shared->statistics().Initialized()) {
285 _shared->SetLastError(VE_NOT_INITED, kTraceError);
286 return -1;
287 }
288 if (channel == -1) {
289 return _shared->output_mixer()->GetSpeechOutputLevelFullRange(
290 (uint32_t&)level);
291 } else {
292 voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
293 voe::Channel* channelPtr = ch.channel();
294 if (channelPtr == NULL) {
295 _shared->SetLastError(
296 VE_CHANNEL_NOT_VALID, kTraceError,
297 "GetSpeechOutputLevelFullRange() failed to locate channel");
298 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +0000299 }
Jelena Marusic0d266052015-05-04 14:15:32 +0200300 channelPtr->GetSpeechOutputLevelFullRange((uint32_t&)level);
301 }
302 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000303}
304
305int VoEVolumeControlImpl::SetChannelOutputVolumeScaling(int channel,
Jelena Marusic0d266052015-05-04 14:15:32 +0200306 float scaling) {
307 WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
niklase@google.com470e71d2011-07-07 08:21:25 +0000308 "SetChannelOutputVolumeScaling(channel=%d, scaling=%3.2f)",
309 channel, scaling);
Jelena Marusic0d266052015-05-04 14:15:32 +0200310 if (!_shared->statistics().Initialized()) {
311 _shared->SetLastError(VE_NOT_INITED, kTraceError);
312 return -1;
313 }
314 if (scaling < kMinOutputVolumeScaling || scaling > kMaxOutputVolumeScaling) {
315 _shared->SetLastError(VE_INVALID_ARGUMENT, kTraceError,
316 "SetChannelOutputVolumeScaling() invalid parameter");
317 return -1;
318 }
319 voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
320 voe::Channel* channelPtr = ch.channel();
321 if (channelPtr == NULL) {
322 _shared->SetLastError(
323 VE_CHANNEL_NOT_VALID, kTraceError,
324 "SetChannelOutputVolumeScaling() failed to locate channel");
325 return -1;
326 }
327 return channelPtr->SetChannelOutputVolumeScaling(scaling);
niklase@google.com470e71d2011-07-07 08:21:25 +0000328}
329
330int VoEVolumeControlImpl::GetChannelOutputVolumeScaling(int channel,
Jelena Marusic0d266052015-05-04 14:15:32 +0200331 float& scaling) {
Jelena Marusic0d266052015-05-04 14:15:32 +0200332 if (!_shared->statistics().Initialized()) {
333 _shared->SetLastError(VE_NOT_INITED, kTraceError);
334 return -1;
335 }
336 voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
337 voe::Channel* channelPtr = ch.channel();
338 if (channelPtr == NULL) {
339 _shared->SetLastError(
340 VE_CHANNEL_NOT_VALID, kTraceError,
341 "GetChannelOutputVolumeScaling() failed to locate channel");
342 return -1;
343 }
344 return channelPtr->GetChannelOutputVolumeScaling(scaling);
niklase@google.com470e71d2011-07-07 08:21:25 +0000345}
346
347int VoEVolumeControlImpl::SetOutputVolumePan(int channel,
348 float left,
Jelena Marusic0d266052015-05-04 14:15:32 +0200349 float right) {
350 WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
niklase@google.com470e71d2011-07-07 08:21:25 +0000351 "SetOutputVolumePan(channel=%d, left=%2.1f, right=%2.1f)",
352 channel, left, right);
niklase@google.com470e71d2011-07-07 08:21:25 +0000353
Jelena Marusic0d266052015-05-04 14:15:32 +0200354 if (!_shared->statistics().Initialized()) {
355 _shared->SetLastError(VE_NOT_INITED, kTraceError);
356 return -1;
357 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000358
Jelena Marusic0d266052015-05-04 14:15:32 +0200359 bool available(false);
360 _shared->audio_device()->StereoPlayoutIsAvailable(&available);
361 if (!available) {
362 _shared->SetLastError(VE_FUNC_NO_STEREO, kTraceError,
363 "SetOutputVolumePan() stereo playout not supported");
364 return -1;
365 }
366 if ((left < kMinOutputVolumePanning) || (left > kMaxOutputVolumePanning) ||
367 (right < kMinOutputVolumePanning) || (right > kMaxOutputVolumePanning)) {
368 _shared->SetLastError(VE_INVALID_ARGUMENT, kTraceError,
369 "SetOutputVolumePan() invalid parameter");
370 return -1;
371 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000372
Jelena Marusic0d266052015-05-04 14:15:32 +0200373 if (channel == -1) {
374 // Master balance (affectes the signal after output mixing)
375 return _shared->output_mixer()->SetOutputVolumePan(left, right);
376 }
377 // Per-channel balance (affects the signal before output mixing)
378 voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
379 voe::Channel* channelPtr = ch.channel();
380 if (channelPtr == NULL) {
381 _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
382 "SetOutputVolumePan() failed to locate channel");
383 return -1;
384 }
385 return channelPtr->SetOutputVolumePan(left, right);
niklase@google.com470e71d2011-07-07 08:21:25 +0000386}
387
388int VoEVolumeControlImpl::GetOutputVolumePan(int channel,
389 float& left,
Jelena Marusic0d266052015-05-04 14:15:32 +0200390 float& right) {
Jelena Marusic0d266052015-05-04 14:15:32 +0200391 if (!_shared->statistics().Initialized()) {
392 _shared->SetLastError(VE_NOT_INITED, kTraceError);
393 return -1;
394 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000395
Jelena Marusic0d266052015-05-04 14:15:32 +0200396 bool available(false);
397 _shared->audio_device()->StereoPlayoutIsAvailable(&available);
398 if (!available) {
399 _shared->SetLastError(VE_FUNC_NO_STEREO, kTraceError,
400 "GetOutputVolumePan() stereo playout not supported");
401 return -1;
402 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000403
Jelena Marusic0d266052015-05-04 14:15:32 +0200404 if (channel == -1) {
405 return _shared->output_mixer()->GetOutputVolumePan(left, right);
406 }
407 voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
408 voe::Channel* channelPtr = ch.channel();
409 if (channelPtr == NULL) {
410 _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
411 "GetOutputVolumePan() failed to locate channel");
412 return -1;
413 }
414 return channelPtr->GetOutputVolumePan(left, right);
niklase@google.com470e71d2011-07-07 08:21:25 +0000415}
416
417#endif // #ifdef WEBRTC_VOICE_ENGINE_VOLUME_CONTROL_API
418
419} // namespace webrtc