blob: f0d165217a2046a0080edfc4fb78be6dc5437e7f [file] [log] [blame]
andrew@webrtc.orga7b57da2012-10-22 18:19:23 +00001/*
2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
3 *
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
11#include "voe_volume_control_impl.h"
12
13#include "channel.h"
14#include "critical_section_wrapper.h"
15#include "output_mixer.h"
16#include "trace.h"
17#include "transmit_mixer.h"
18#include "voe_errors.h"
19#include "voice_engine_impl.h"
20
21namespace webrtc {
22
23VoEVolumeControl* VoEVolumeControl::GetInterface(VoiceEngine* voiceEngine)
24{
25#ifndef WEBRTC_VOICE_ENGINE_VOLUME_CONTROL_API
26 return NULL;
27#else
28 if (NULL == voiceEngine)
29 {
30 return NULL;
31 }
32 VoiceEngineImpl* s = reinterpret_cast<VoiceEngineImpl*>(voiceEngine);
33 s->AddRef();
34 return s;
35#endif
36}
37
38#ifdef WEBRTC_VOICE_ENGINE_VOLUME_CONTROL_API
39
40VoEVolumeControlImpl::VoEVolumeControlImpl(voe::SharedData* shared)
41 : _shared(shared)
42{
43 WEBRTC_TRACE(kTraceMemory, kTraceVoice, VoEId(_shared->instance_id(), -1),
44 "VoEVolumeControlImpl::VoEVolumeControlImpl() - ctor");
45}
46
47VoEVolumeControlImpl::~VoEVolumeControlImpl()
48{
49 WEBRTC_TRACE(kTraceMemory, kTraceVoice, VoEId(_shared->instance_id(), -1),
50 "VoEVolumeControlImpl::~VoEVolumeControlImpl() - dtor");
51}
52
53int VoEVolumeControlImpl::SetSpeakerVolume(unsigned int volume)
54{
55 WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
56 "SetSpeakerVolume(volume=%u)", volume);
57 IPHONE_NOT_SUPPORTED(_shared->statistics());
58
59 if (!_shared->statistics().Initialized())
60 {
61 _shared->SetLastError(VE_NOT_INITED, kTraceError);
62 return -1;
63 }
64 if (volume > kMaxVolumeLevel)
65 {
66 _shared->SetLastError(VE_INVALID_ARGUMENT, kTraceError,
67 "SetSpeakerVolume() invalid argument");
68 return -1;
69 }
70
71 WebRtc_UWord32 maxVol(0);
72 WebRtc_UWord32 spkrVol(0);
73
74 // scale: [0,kMaxVolumeLevel] -> [0,MaxSpeakerVolume]
75 if (_shared->audio_device()->MaxSpeakerVolume(&maxVol) != 0)
76 {
77 _shared->SetLastError(VE_MIC_VOL_ERROR, kTraceError,
78 "SetSpeakerVolume() failed to get max volume");
79 return -1;
80 }
81 // Round the value and avoid floating computation.
82 spkrVol = (WebRtc_UWord32)((volume * maxVol +
83 (int)(kMaxVolumeLevel / 2)) / (kMaxVolumeLevel));
84
85 // set the actual volume using the audio mixer
86 if (_shared->audio_device()->SetSpeakerVolume(spkrVol) != 0)
87 {
88 _shared->SetLastError(VE_MIC_VOL_ERROR, kTraceError,
89 "SetSpeakerVolume() failed to set speaker volume");
90 return -1;
91 }
92 return 0;
93}
94
95int VoEVolumeControlImpl::GetSpeakerVolume(unsigned int& volume)
96{
97 WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
98 "GetSpeakerVolume()");
99 IPHONE_NOT_SUPPORTED(_shared->statistics());
100
101 if (!_shared->statistics().Initialized())
102 {
103 _shared->SetLastError(VE_NOT_INITED, kTraceError);
104 return -1;
105 }
106
107 WebRtc_UWord32 spkrVol(0);
108 WebRtc_UWord32 maxVol(0);
109
110 if (_shared->audio_device()->SpeakerVolume(&spkrVol) != 0)
111 {
112 _shared->SetLastError(VE_GET_MIC_VOL_ERROR, kTraceError,
113 "GetSpeakerVolume() unable to get speaker volume");
114 return -1;
115 }
116
117 // scale: [0, MaxSpeakerVolume] -> [0, kMaxVolumeLevel]
118 if (_shared->audio_device()->MaxSpeakerVolume(&maxVol) != 0)
119 {
120 _shared->SetLastError(VE_GET_MIC_VOL_ERROR, kTraceError,
121 "GetSpeakerVolume() unable to get max speaker volume");
122 return -1;
123 }
124 // Round the value and avoid floating computation.
125 volume = (WebRtc_UWord32) ((spkrVol * kMaxVolumeLevel +
126 (int)(maxVol / 2)) / (maxVol));
127
128 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
129 VoEId(_shared->instance_id(), -1),
130 "GetSpeakerVolume() => volume=%d", volume);
131 return 0;
132}
133
134int VoEVolumeControlImpl::SetSystemOutputMute(bool enable)
135{
136 WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
137 "GetSystemOutputMute(enabled=%d)", enable);
138
139 if (!_shared->statistics().Initialized())
140 {
141 _shared->SetLastError(VE_NOT_INITED, kTraceError);
142 return -1;
143 }
144
145 if (_shared->audio_device()->SetSpeakerMute(enable) != 0)
146 {
147 _shared->SetLastError(VE_GET_MIC_VOL_ERROR, kTraceError,
148 "SpeakerMute() unable to Set speaker mute");
149 return -1;
150 }
151
152 return 0;
153}
154
155int VoEVolumeControlImpl::GetSystemOutputMute(bool& enabled)
156{
157 WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
158 "GetSystemOutputMute(enabled=?)");
159
160 if (!_shared->statistics().Initialized())
161 {
162 _shared->SetLastError(VE_NOT_INITED, kTraceError);
163 return -1;
164 }
165
166 if (_shared->audio_device()->SpeakerMute(&enabled) != 0)
167 {
168 _shared->SetLastError(VE_GET_MIC_VOL_ERROR, kTraceError,
169 "SpeakerMute() unable to get speaker mute state");
170 return -1;
171 }
172 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
173 VoEId(_shared->instance_id(), -1),
174 "GetSystemOutputMute() => %d", enabled);
175 return 0;
176}
177
178int VoEVolumeControlImpl::SetMicVolume(unsigned int volume)
179{
180 WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
181 "SetMicVolume(volume=%u)", volume);
182 ANDROID_NOT_SUPPORTED(_shared->statistics());
183 IPHONE_NOT_SUPPORTED(_shared->statistics());
184
185 if (!_shared->statistics().Initialized())
186 {
187 _shared->SetLastError(VE_NOT_INITED, kTraceError);
188 return -1;
189 }
190 if (volume > kMaxVolumeLevel)
191 {
192 _shared->SetLastError(VE_INVALID_ARGUMENT, kTraceError,
193 "SetMicVolume() invalid argument");
194 return -1;
195 }
196
197 WebRtc_UWord32 maxVol(0);
198 WebRtc_UWord32 micVol(0);
199
200 // scale: [0, kMaxVolumeLevel] -> [0,MaxMicrophoneVolume]
201 if (_shared->audio_device()->MaxMicrophoneVolume(&maxVol) != 0)
202 {
203 _shared->SetLastError(VE_MIC_VOL_ERROR, kTraceError,
204 "SetMicVolume() failed to get max volume");
205 return -1;
206 }
207
208 if (volume == kMaxVolumeLevel) {
209 // On Linux running pulse, users are able to set the volume above 100%
210 // through the volume control panel, where the +100% range is digital
211 // scaling. WebRTC does not support setting the volume above 100%, and
212 // simply ignores changing the volume if the user tries to set it to
213 // |kMaxVolumeLevel| while the current volume is higher than |maxVol|.
214 if (_shared->audio_device()->MicrophoneVolume(&micVol) != 0) {
215 _shared->SetLastError(VE_GET_MIC_VOL_ERROR, kTraceError,
216 "SetMicVolume() unable to get microphone volume");
217 return -1;
218 }
219 if (micVol >= maxVol)
220 return 0;
221 }
222
223 // Round the value and avoid floating point computation.
224 micVol = (WebRtc_UWord32) ((volume * maxVol +
225 (int)(kMaxVolumeLevel / 2)) / (kMaxVolumeLevel));
226
227 // set the actual volume using the audio mixer
228 if (_shared->audio_device()->SetMicrophoneVolume(micVol) != 0)
229 {
230 _shared->SetLastError(VE_MIC_VOL_ERROR, kTraceError,
231 "SetMicVolume() failed to set mic volume");
232 return -1;
233 }
234 return 0;
235}
236
237int VoEVolumeControlImpl::GetMicVolume(unsigned int& volume)
238{
239 WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
240 "GetMicVolume()");
241 ANDROID_NOT_SUPPORTED(_shared->statistics());
242 IPHONE_NOT_SUPPORTED(_shared->statistics());
243
244 if (!_shared->statistics().Initialized())
245 {
246 _shared->SetLastError(VE_NOT_INITED, kTraceError);
247 return -1;
248 }
249
250 WebRtc_UWord32 micVol(0);
251 WebRtc_UWord32 maxVol(0);
252
253 if (_shared->audio_device()->MicrophoneVolume(&micVol) != 0)
254 {
255 _shared->SetLastError(VE_GET_MIC_VOL_ERROR, kTraceError,
256 "GetMicVolume() unable to get microphone volume");
257 return -1;
258 }
259
260 // scale: [0, MaxMicrophoneVolume] -> [0, kMaxVolumeLevel]
261 if (_shared->audio_device()->MaxMicrophoneVolume(&maxVol) != 0)
262 {
263 _shared->SetLastError(VE_GET_MIC_VOL_ERROR, kTraceError,
264 "GetMicVolume() unable to get max microphone volume");
265 return -1;
266 }
267 if (micVol < maxVol) {
268 // Round the value and avoid floating point calculation.
269 volume = (WebRtc_UWord32) ((micVol * kMaxVolumeLevel +
270 (int)(maxVol / 2)) / (maxVol));
271 } else {
272 // Truncate the value to the kMaxVolumeLevel.
273 volume = kMaxVolumeLevel;
274 }
275
276 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
277 VoEId(_shared->instance_id(), -1),
278 "GetMicVolume() => volume=%d", volume);
279 return 0;
280}
281
282int VoEVolumeControlImpl::SetInputMute(int channel, bool enable)
283{
284 WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
285 "SetInputMute(channel=%d, enable=%d)", channel, enable);
286
287 if (!_shared->statistics().Initialized())
288 {
289 _shared->SetLastError(VE_NOT_INITED, kTraceError);
290 return -1;
291 }
292 if (channel == -1)
293 {
294 // Mute before demultiplexing <=> affects all channels
295 return _shared->transmit_mixer()->SetMute(enable);
296 }
297 else
298 {
299 // Mute after demultiplexing <=> affects one channel only
300 voe::ScopedChannel sc(_shared->channel_manager(), channel);
301 voe::Channel* channelPtr = sc.ChannelPtr();
302 if (channelPtr == NULL)
303 {
304 _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
305 "SetInputMute() failed to locate channel");
306 return -1;
307 }
308 return channelPtr->SetMute(enable);
309 }
310 return 0;
311}
312
313int VoEVolumeControlImpl::GetInputMute(int channel, bool& enabled)
314{
315 WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
316 "GetInputMute(channel=%d)", channel);
317
318 if (!_shared->statistics().Initialized())
319 {
320 _shared->SetLastError(VE_NOT_INITED, kTraceError);
321 return -1;
322 }
323 if (channel == -1)
324 {
325 enabled = _shared->transmit_mixer()->Mute();
326 }
327 else
328 {
329 voe::ScopedChannel sc(_shared->channel_manager(), channel);
330 voe::Channel* channelPtr = sc.ChannelPtr();
331 if (channelPtr == NULL)
332 {
333 _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
334 "SetInputMute() failed to locate channel");
335 return -1;
336 }
337 enabled = channelPtr->Mute();
338 }
339 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
340 VoEId(_shared->instance_id(), -1),
341 "GetInputMute() => enabled = %d", (int)enabled);
342 return 0;
343}
344
345int VoEVolumeControlImpl::SetSystemInputMute(bool enable)
346{
347 WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
348 "SetSystemInputMute(enabled=%d)", enable);
349
350 if (!_shared->statistics().Initialized())
351 {
352 _shared->SetLastError(VE_NOT_INITED, kTraceError);
353 return -1;
354 }
355
356 if (_shared->audio_device()->SetMicrophoneMute(enable) != 0)
357 {
358 _shared->SetLastError(VE_GET_MIC_VOL_ERROR, kTraceError,
359 "MicrophoneMute() unable to set microphone mute state");
360 return -1;
361 }
362
363 return 0;
364}
365
366int VoEVolumeControlImpl::GetSystemInputMute(bool& enabled)
367{
368 WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
369 "GetSystemInputMute(enabled=?)");
370
371 if (!_shared->statistics().Initialized())
372 {
373 _shared->SetLastError(VE_NOT_INITED, kTraceError);
374 return -1;
375 }
376
377 if (_shared->audio_device()->MicrophoneMute(&enabled) != 0)
378 {
379 _shared->SetLastError(VE_GET_MIC_VOL_ERROR, kTraceError,
380 "MicrophoneMute() unable to get microphone mute state");
381 return -1;
382 }
383 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
384 VoEId(_shared->instance_id(), -1),
385 "GetSystemInputMute() => %d", enabled);
386 return 0;
387}
388
389int VoEVolumeControlImpl::GetSpeechInputLevel(unsigned int& level)
390{
391 WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
392 "GetSpeechInputLevel()");
393
394 if (!_shared->statistics().Initialized())
395 {
396 _shared->SetLastError(VE_NOT_INITED, kTraceError);
397 return -1;
398 }
399 WebRtc_Word8 currentLevel = _shared->transmit_mixer()->AudioLevel();
400 level = static_cast<unsigned int> (currentLevel);
401 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
402 VoEId(_shared->instance_id(), -1),
403 "GetSpeechInputLevel() => %d", level);
404 return 0;
405}
406
407int VoEVolumeControlImpl::GetSpeechOutputLevel(int channel,
408 unsigned int& level)
409{
410 WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
411 "GetSpeechOutputLevel(channel=%d, level=?)", channel);
412
413 if (!_shared->statistics().Initialized())
414 {
415 _shared->SetLastError(VE_NOT_INITED, kTraceError);
416 return -1;
417 }
418 if (channel == -1)
419 {
420 return _shared->output_mixer()->GetSpeechOutputLevel(
421 (WebRtc_UWord32&)level);
422 }
423 else
424 {
425 voe::ScopedChannel sc(_shared->channel_manager(), channel);
426 voe::Channel* channelPtr = sc.ChannelPtr();
427 if (channelPtr == NULL)
428 {
429 _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
430 "GetSpeechOutputLevel() failed to locate channel");
431 return -1;
432 }
433 channelPtr->GetSpeechOutputLevel((WebRtc_UWord32&)level);
434 }
435 return 0;
436}
437
438int VoEVolumeControlImpl::GetSpeechInputLevelFullRange(unsigned int& level)
439{
440 WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
441 "GetSpeechInputLevelFullRange(level=?)");
442
443 if (!_shared->statistics().Initialized())
444 {
445 _shared->SetLastError(VE_NOT_INITED, kTraceError);
446 return -1;
447 }
448 WebRtc_Word16 currentLevel = _shared->transmit_mixer()->
449 AudioLevelFullRange();
450 level = static_cast<unsigned int> (currentLevel);
451 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
452 VoEId(_shared->instance_id(), -1),
453 "GetSpeechInputLevelFullRange() => %d", level);
454 return 0;
455}
456
457int VoEVolumeControlImpl::GetSpeechOutputLevelFullRange(int channel,
458 unsigned int& level)
459{
460 WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
461 "GetSpeechOutputLevelFullRange(channel=%d, level=?)", channel);
462
463 if (!_shared->statistics().Initialized())
464 {
465 _shared->SetLastError(VE_NOT_INITED, kTraceError);
466 return -1;
467 }
468 if (channel == -1)
469 {
470 return _shared->output_mixer()->GetSpeechOutputLevelFullRange(
471 (WebRtc_UWord32&)level);
472 }
473 else
474 {
475 voe::ScopedChannel sc(_shared->channel_manager(), channel);
476 voe::Channel* channelPtr = sc.ChannelPtr();
477 if (channelPtr == NULL)
478 {
479 _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
480 "GetSpeechOutputLevelFullRange() failed to locate channel");
481 return -1;
482 }
483 channelPtr->GetSpeechOutputLevelFullRange((WebRtc_UWord32&)level);
484 }
485 return 0;
486}
487
488int VoEVolumeControlImpl::SetChannelOutputVolumeScaling(int channel,
489 float scaling)
490{
491 WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
492 "SetChannelOutputVolumeScaling(channel=%d, scaling=%3.2f)",
493 channel, scaling);
494 IPHONE_NOT_SUPPORTED(_shared->statistics());
495 if (!_shared->statistics().Initialized())
496 {
497 _shared->SetLastError(VE_NOT_INITED, kTraceError);
498 return -1;
499 }
500 if (scaling < kMinOutputVolumeScaling ||
501 scaling > kMaxOutputVolumeScaling)
502 {
503 _shared->SetLastError(VE_INVALID_ARGUMENT, kTraceError,
504 "SetChannelOutputVolumeScaling() invalid parameter");
505 return -1;
506 }
507 voe::ScopedChannel sc(_shared->channel_manager(), channel);
508 voe::Channel* channelPtr = sc.ChannelPtr();
509 if (channelPtr == NULL)
510 {
511 _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
512 "SetChannelOutputVolumeScaling() failed to locate channel");
513 return -1;
514 }
515 return channelPtr->SetChannelOutputVolumeScaling(scaling);
516}
517
518int VoEVolumeControlImpl::GetChannelOutputVolumeScaling(int channel,
519 float& scaling)
520{
521 WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
522 "GetChannelOutputVolumeScaling(channel=%d, scaling=?)", channel);
523 IPHONE_NOT_SUPPORTED(_shared->statistics());
524 if (!_shared->statistics().Initialized())
525 {
526 _shared->SetLastError(VE_NOT_INITED, kTraceError);
527 return -1;
528 }
529 voe::ScopedChannel sc(_shared->channel_manager(), channel);
530 voe::Channel* channelPtr = sc.ChannelPtr();
531 if (channelPtr == NULL)
532 {
533 _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
534 "GetChannelOutputVolumeScaling() failed to locate channel");
535 return -1;
536 }
537 return channelPtr->GetChannelOutputVolumeScaling(scaling);
538}
539
540int VoEVolumeControlImpl::SetOutputVolumePan(int channel,
541 float left,
542 float right)
543{
544 WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
545 "SetOutputVolumePan(channel=%d, left=%2.1f, right=%2.1f)",
546 channel, left, right);
547 ANDROID_NOT_SUPPORTED(_shared->statistics());
548 IPHONE_NOT_SUPPORTED(_shared->statistics());
549
550 if (!_shared->statistics().Initialized())
551 {
552 _shared->SetLastError(VE_NOT_INITED, kTraceError);
553 return -1;
554 }
555
556 bool available(false);
557 _shared->audio_device()->StereoPlayoutIsAvailable(&available);
558 if (!available)
559 {
560 _shared->SetLastError(VE_FUNC_NO_STEREO, kTraceError,
561 "SetOutputVolumePan() stereo playout not supported");
562 return -1;
563 }
564 if ((left < kMinOutputVolumePanning) ||
565 (left > kMaxOutputVolumePanning) ||
566 (right < kMinOutputVolumePanning) ||
567 (right > kMaxOutputVolumePanning))
568 {
569 _shared->SetLastError(VE_INVALID_ARGUMENT, kTraceError,
570 "SetOutputVolumePan() invalid parameter");
571 return -1;
572 }
573
574 if (channel == -1)
575 {
576 // Master balance (affectes the signal after output mixing)
577 return _shared->output_mixer()->SetOutputVolumePan(left, right);
578 }
579 else
580 {
581 // Per-channel balance (affects the signal before output mixing)
582 voe::ScopedChannel sc(_shared->channel_manager(), channel);
583 voe::Channel* channelPtr = sc.ChannelPtr();
584 if (channelPtr == NULL)
585 {
586 _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
587 "SetOutputVolumePan() failed to locate channel");
588 return -1;
589 }
590 return channelPtr->SetOutputVolumePan(left, right);
591 }
592 return 0;
593}
594
595int VoEVolumeControlImpl::GetOutputVolumePan(int channel,
596 float& left,
597 float& right)
598{
599 WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
600 "GetOutputVolumePan(channel=%d, left=?, right=?)", channel);
601 ANDROID_NOT_SUPPORTED(_shared->statistics());
602 IPHONE_NOT_SUPPORTED(_shared->statistics());
603
604 if (!_shared->statistics().Initialized())
605 {
606 _shared->SetLastError(VE_NOT_INITED, kTraceError);
607 return -1;
608 }
609
610 bool available(false);
611 _shared->audio_device()->StereoPlayoutIsAvailable(&available);
612 if (!available)
613 {
614 _shared->SetLastError(VE_FUNC_NO_STEREO, kTraceError,
615 "GetOutputVolumePan() stereo playout not supported");
616 return -1;
617 }
618
619 if (channel == -1)
620 {
621 return _shared->output_mixer()->GetOutputVolumePan(left, right);
622 }
623 else
624 {
625 voe::ScopedChannel sc(_shared->channel_manager(), channel);
626 voe::Channel* channelPtr = sc.ChannelPtr();
627 if (channelPtr == NULL)
628 {
629 _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
630 "GetOutputVolumePan() failed to locate channel");
631 return -1;
632 }
633 return channelPtr->GetOutputVolumePan(left, right);
634 }
635 return 0;
636}
637
638#endif // #ifdef WEBRTC_VOICE_ENGINE_VOLUME_CONTROL_API
639
640} // namespace webrtc