| /* |
| * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. |
| * |
| * Use of this source code is governed by a BSD-style license |
| * that can be found in the LICENSE file in the root of the source |
| * tree. An additional intellectual property rights grant can be found |
| * in the file PATENTS. All contributing project authors may |
| * be found in the AUTHORS file in the root of the source tree. |
| */ |
| |
| #include "voe_volume_control_impl.h" |
| |
| #include "channel.h" |
| #include "critical_section_wrapper.h" |
| #include "output_mixer.h" |
| #include "trace.h" |
| #include "transmit_mixer.h" |
| #include "voe_errors.h" |
| #include "voice_engine_impl.h" |
| |
| namespace webrtc { |
| |
| VoEVolumeControl* VoEVolumeControl::GetInterface(VoiceEngine* voiceEngine) |
| { |
| #ifndef WEBRTC_VOICE_ENGINE_VOLUME_CONTROL_API |
| return NULL; |
| #else |
| if (NULL == voiceEngine) |
| { |
| return NULL; |
| } |
| VoiceEngineImpl* s = |
| reinterpret_cast<VoiceEngineImpl*> (voiceEngine); |
| VoEVolumeControlImpl* d = s; |
| (*d)++; |
| return (d); |
| #endif |
| } |
| |
| #ifdef WEBRTC_VOICE_ENGINE_VOLUME_CONTROL_API |
| |
| VoEVolumeControlImpl::VoEVolumeControlImpl() |
| { |
| WEBRTC_TRACE(kTraceMemory, kTraceVoice, VoEId(_instanceId,-1), |
| "VoEVolumeControlImpl::VoEVolumeControlImpl() - ctor"); |
| } |
| |
| VoEVolumeControlImpl::~VoEVolumeControlImpl() |
| { |
| WEBRTC_TRACE(kTraceMemory, kTraceVoice, VoEId(_instanceId,-1), |
| "VoEVolumeControlImpl::~VoEVolumeControlImpl() - dtor"); |
| } |
| |
| int VoEVolumeControlImpl::Release() |
| { |
| WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_instanceId,-1), |
| "VoEVolumeControl::Release()"); |
| (*this)--; |
| int refCount = GetCount(); |
| if (refCount < 0) |
| { |
| Reset(); // reset reference counter to zero => OK to delete VE |
| _engineStatistics.SetLastError( |
| VE_INTERFACE_NOT_FOUND, kTraceWarning); |
| return (-1); |
| } |
| WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, VoEId(_instanceId,-1), |
| "VoEVolumeControl reference counter = %d", refCount); |
| return (refCount); |
| } |
| |
| int VoEVolumeControlImpl::SetSpeakerVolume(unsigned int volume) |
| { |
| WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_instanceId,-1), |
| "SetSpeakerVolume(volume=%u)", volume); |
| IPHONE_NOT_SUPPORTED(); |
| |
| if (!_engineStatistics.Initialized()) |
| { |
| _engineStatistics.SetLastError(VE_NOT_INITED, kTraceError); |
| return -1; |
| } |
| if (volume > kMaxVolumeLevel) |
| { |
| _engineStatistics.SetLastError( |
| VE_INVALID_ARGUMENT, kTraceError, |
| "SetSpeakerVolume() invalid argument"); |
| return -1; |
| } |
| |
| WebRtc_UWord32 maxVol(0); |
| WebRtc_UWord32 spkrVol(0); |
| |
| // scale: [0,kMaxVolumeLevel] -> [0,MaxSpeakerVolume] |
| if (_audioDevicePtr->MaxSpeakerVolume(&maxVol) != 0) |
| { |
| _engineStatistics.SetLastError( |
| VE_MIC_VOL_ERROR, kTraceError, |
| "SetSpeakerVolume() failed to get max volume"); |
| return -1; |
| } |
| // round the value and avoid floating computation |
| spkrVol = (WebRtc_UWord32)((volume * maxVol + |
| (int)(kMaxVolumeLevel / 2)) / (kMaxVolumeLevel)); |
| |
| // set the actual volume using the audio mixer |
| if (_audioDevicePtr->SetSpeakerVolume(spkrVol) != 0) |
| { |
| _engineStatistics.SetLastError( |
| VE_MIC_VOL_ERROR, kTraceError, |
| "SetSpeakerVolume() failed to set speaker volume"); |
| return -1; |
| } |
| return 0; |
| } |
| |
| int VoEVolumeControlImpl::GetSpeakerVolume(unsigned int& volume) |
| { |
| WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_instanceId,-1), |
| "GetSpeakerVolume()"); |
| IPHONE_NOT_SUPPORTED(); |
| |
| if (!_engineStatistics.Initialized()) |
| { |
| _engineStatistics.SetLastError(VE_NOT_INITED, kTraceError); |
| return -1; |
| } |
| |
| WebRtc_UWord32 spkrVol(0); |
| WebRtc_UWord32 maxVol(0); |
| |
| if (_audioDevicePtr->SpeakerVolume(&spkrVol) != 0) |
| { |
| _engineStatistics.SetLastError( |
| VE_GET_MIC_VOL_ERROR, kTraceError, |
| "GetSpeakerVolume() unable to get speaker volume"); |
| return -1; |
| } |
| |
| // scale: [0, MaxSpeakerVolume] -> [0, kMaxVolumeLevel] |
| if (_audioDevicePtr->MaxSpeakerVolume(&maxVol) != 0) |
| { |
| _engineStatistics.SetLastError( |
| VE_GET_MIC_VOL_ERROR, kTraceError, |
| "GetSpeakerVolume() unable to get max speaker volume"); |
| return -1; |
| } |
| // round the value and avoid floating computation |
| volume = (WebRtc_UWord32) ((spkrVol * kMaxVolumeLevel + |
| (int)(maxVol / 2)) / (maxVol)); |
| |
| WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, VoEId(_instanceId,-1), |
| "GetSpeakerVolume() => volume=%d", volume); |
| return 0; |
| } |
| |
| int VoEVolumeControlImpl::SetSystemOutputMute(bool enable) |
| { |
| WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_instanceId,-1), |
| "GetSystemOutputMute(enabled=%d)", enable); |
| |
| if (!_engineStatistics.Initialized()) |
| { |
| _engineStatistics.SetLastError(VE_NOT_INITED, kTraceError); |
| return -1; |
| } |
| |
| if (_audioDevicePtr->SetSpeakerMute(enable) != 0) |
| { |
| _engineStatistics.SetLastError( |
| VE_GET_MIC_VOL_ERROR, kTraceError, |
| "SpeakerMute() unable to Set speaker mute"); |
| return -1; |
| } |
| |
| return 0; |
| } |
| |
| int VoEVolumeControlImpl::GetSystemOutputMute(bool& enabled) |
| { |
| WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_instanceId,-1), |
| "GetSystemOutputMute(enabled=?)"); |
| |
| if (!_engineStatistics.Initialized()) |
| { |
| _engineStatistics.SetLastError(VE_NOT_INITED, kTraceError); |
| return -1; |
| } |
| |
| if (_audioDevicePtr->SpeakerMute(&enabled) != 0) |
| { |
| _engineStatistics.SetLastError( |
| VE_GET_MIC_VOL_ERROR, kTraceError, |
| "SpeakerMute() unable to get speaker mute state"); |
| return -1; |
| } |
| WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, VoEId(_instanceId,-1), |
| "GetSystemOutputMute() => %d", enabled); |
| return 0; |
| } |
| |
| int VoEVolumeControlImpl::SetMicVolume(unsigned int volume) |
| { |
| WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_instanceId,-1), |
| "SetMicVolume(volume=%u)", volume); |
| ANDROID_NOT_SUPPORTED(_engineStatistics); |
| IPHONE_NOT_SUPPORTED(); |
| |
| if (!_engineStatistics.Initialized()) |
| { |
| _engineStatistics.SetLastError(VE_NOT_INITED, kTraceError); |
| return -1; |
| } |
| if (volume > kMaxVolumeLevel) |
| { |
| _engineStatistics.SetLastError( |
| VE_INVALID_ARGUMENT, kTraceError, |
| "SetMicVolume() invalid argument"); |
| return -1; |
| } |
| |
| WebRtc_UWord32 maxVol(0); |
| WebRtc_UWord32 micVol(0); |
| |
| // scale: [0, kMaxVolumeLevel] -> [0,MaxMicrophoneVolume] |
| if (_audioDevicePtr->MaxMicrophoneVolume(&maxVol) != 0) |
| { |
| _engineStatistics.SetLastError( |
| VE_MIC_VOL_ERROR, kTraceError, |
| "SetMicVolume() failed to get max volume"); |
| return -1; |
| } |
| // round the value and avoid floating point computation |
| micVol = (WebRtc_UWord32) ((volume * maxVol + |
| (int)(kMaxVolumeLevel / 2)) / (kMaxVolumeLevel)); |
| |
| // set the actual volume using the audio mixer |
| if (_audioDevicePtr->SetMicrophoneVolume(micVol) != 0) |
| { |
| _engineStatistics.SetLastError( |
| VE_MIC_VOL_ERROR, kTraceError, |
| "SetMicVolume() failed to set mic volume"); |
| return -1; |
| } |
| return 0; |
| } |
| |
| int VoEVolumeControlImpl::GetMicVolume(unsigned int& volume) |
| { |
| WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_instanceId,-1), |
| "GetMicVolume()"); |
| ANDROID_NOT_SUPPORTED(_engineStatistics); |
| IPHONE_NOT_SUPPORTED(); |
| |
| if (!_engineStatistics.Initialized()) |
| { |
| _engineStatistics.SetLastError(VE_NOT_INITED, kTraceError); |
| return -1; |
| } |
| |
| WebRtc_UWord32 micVol(0); |
| WebRtc_UWord32 maxVol(0); |
| |
| if (_audioDevicePtr->MicrophoneVolume(&micVol) != 0) |
| { |
| _engineStatistics.SetLastError( |
| VE_GET_MIC_VOL_ERROR, kTraceError, |
| "GetMicVolume() unable to get microphone volume"); |
| return -1; |
| } |
| |
| // scale: [0, MaxMicrophoneVolume] -> [0, kMaxVolumeLevel] |
| if (_audioDevicePtr->MaxMicrophoneVolume(&maxVol) != 0) |
| { |
| _engineStatistics.SetLastError( |
| VE_GET_MIC_VOL_ERROR, kTraceError, |
| "GetMicVolume() unable to get max microphone volume"); |
| return -1; |
| } |
| // round the value and avoid floating point calculation |
| volume = (WebRtc_UWord32) ((micVol * kMaxVolumeLevel + |
| (int)(maxVol / 2)) / (maxVol)); |
| |
| WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, VoEId(_instanceId,-1), |
| "GetMicVolume() => volume=%d", volume); |
| return 0; |
| } |
| |
| int VoEVolumeControlImpl::SetInputMute(int channel, bool enable) |
| { |
| WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_instanceId,-1), |
| "SetInputMute(channel=%d, enable=%d)", channel, enable); |
| |
| if (!_engineStatistics.Initialized()) |
| { |
| _engineStatistics.SetLastError(VE_NOT_INITED, kTraceError); |
| return -1; |
| } |
| if (channel == -1) |
| { |
| // Mute before demultiplexing <=> affects all channels |
| return _transmitMixerPtr->SetMute(enable); |
| } |
| else |
| { |
| // Mute after demultiplexing <=> affects one channel only |
| voe::ScopedChannel sc(_channelManager, channel); |
| voe::Channel* channelPtr = sc.ChannelPtr(); |
| if (channelPtr == NULL) |
| { |
| _engineStatistics.SetLastError( |
| VE_CHANNEL_NOT_VALID, kTraceError, |
| "SetInputMute() failed to locate channel"); |
| return -1; |
| } |
| return channelPtr->SetMute(enable); |
| } |
| return 0; |
| } |
| |
| int VoEVolumeControlImpl::GetInputMute(int channel, bool& enabled) |
| { |
| WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_instanceId,-1), |
| "GetInputMute(channel=%d)", channel); |
| |
| if (!_engineStatistics.Initialized()) |
| { |
| _engineStatistics.SetLastError(VE_NOT_INITED, kTraceError); |
| return -1; |
| } |
| if (channel == -1) |
| { |
| enabled = _transmitMixerPtr->Mute(); |
| } |
| else |
| { |
| voe::ScopedChannel sc(_channelManager, channel); |
| voe::Channel* channelPtr = sc.ChannelPtr(); |
| if (channelPtr == NULL) |
| { |
| _engineStatistics.SetLastError( |
| VE_CHANNEL_NOT_VALID, kTraceError, |
| "SetInputMute() failed to locate channel"); |
| return -1; |
| } |
| enabled = channelPtr->Mute(); |
| } |
| WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, VoEId(_instanceId,-1), |
| "GetInputMute() => enabled = %d", (int)enabled); |
| return 0; |
| } |
| |
| int VoEVolumeControlImpl::SetSystemInputMute(bool enable) |
| { |
| WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_instanceId,-1), |
| "SetSystemInputMute(enabled=%d)", enable); |
| |
| if (!_engineStatistics.Initialized()) |
| { |
| _engineStatistics.SetLastError(VE_NOT_INITED, kTraceError); |
| return -1; |
| } |
| |
| if (_audioDevicePtr->SetMicrophoneMute(enable) != 0) |
| { |
| _engineStatistics.SetLastError( |
| VE_GET_MIC_VOL_ERROR, kTraceError, |
| "MicrophoneMute() unable to set microphone mute state"); |
| return -1; |
| } |
| |
| return 0; |
| } |
| |
| int VoEVolumeControlImpl::GetSystemInputMute(bool& enabled) |
| { |
| WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_instanceId,-1), |
| "GetSystemInputMute(enabled=?)"); |
| |
| if (!_engineStatistics.Initialized()) |
| { |
| _engineStatistics.SetLastError(VE_NOT_INITED, kTraceError); |
| return -1; |
| } |
| |
| if (_audioDevicePtr->MicrophoneMute(&enabled) != 0) |
| { |
| _engineStatistics.SetLastError( |
| VE_GET_MIC_VOL_ERROR, kTraceError, |
| "MicrophoneMute() unable to get microphone mute state"); |
| return -1; |
| } |
| WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, VoEId(_instanceId,-1), |
| "GetSystemInputMute() => %d", enabled); |
| return 0; |
| } |
| |
| int VoEVolumeControlImpl::GetSpeechInputLevel(unsigned int& level) |
| { |
| WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_instanceId,-1), |
| "GetSpeechInputLevel()"); |
| |
| if (!_engineStatistics.Initialized()) |
| { |
| _engineStatistics.SetLastError(VE_NOT_INITED, kTraceError); |
| return -1; |
| } |
| WebRtc_Word8 currentLevel = _transmitMixerPtr->AudioLevel(); |
| level = static_cast<unsigned int> (currentLevel); |
| WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, VoEId(_instanceId,-1), |
| "GetSpeechInputLevel() => %d", level); |
| return 0; |
| } |
| |
| int VoEVolumeControlImpl::GetSpeechOutputLevel(int channel, |
| unsigned int& level) |
| { |
| WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_instanceId,-1), |
| "GetSpeechOutputLevel(channel=%d, level=?)", channel); |
| |
| if (!_engineStatistics.Initialized()) |
| { |
| _engineStatistics.SetLastError(VE_NOT_INITED, kTraceError); |
| return -1; |
| } |
| if (channel == -1) |
| { |
| return _outputMixerPtr->GetSpeechOutputLevel((WebRtc_UWord32&)level); |
| } |
| else |
| { |
| voe::ScopedChannel sc(_channelManager, channel); |
| voe::Channel* channelPtr = sc.ChannelPtr(); |
| if (channelPtr == NULL) |
| { |
| _engineStatistics.SetLastError( |
| VE_CHANNEL_NOT_VALID, kTraceError, |
| "GetSpeechOutputLevel() failed to locate channel"); |
| return -1; |
| } |
| channelPtr->GetSpeechOutputLevel((WebRtc_UWord32&)level); |
| } |
| return 0; |
| } |
| |
| int VoEVolumeControlImpl::GetSpeechInputLevelFullRange(unsigned int& level) |
| { |
| WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_instanceId,-1), |
| "GetSpeechInputLevelFullRange(level=?)"); |
| |
| if (!_engineStatistics.Initialized()) |
| { |
| _engineStatistics.SetLastError(VE_NOT_INITED, kTraceError); |
| return -1; |
| } |
| WebRtc_Word16 currentLevel = _transmitMixerPtr->AudioLevelFullRange(); |
| level = static_cast<unsigned int> (currentLevel); |
| WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, VoEId(_instanceId,-1), |
| "GetSpeechInputLevelFullRange() => %d", level); |
| return 0; |
| } |
| |
| int VoEVolumeControlImpl::GetSpeechOutputLevelFullRange(int channel, |
| unsigned int& level) |
| { |
| WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_instanceId,-1), |
| "GetSpeechOutputLevelFullRange(channel=%d, level=?)", channel); |
| |
| if (!_engineStatistics.Initialized()) |
| { |
| _engineStatistics.SetLastError(VE_NOT_INITED, kTraceError); |
| return -1; |
| } |
| if (channel == -1) |
| { |
| return _outputMixerPtr->GetSpeechOutputLevelFullRange( |
| (WebRtc_UWord32&)level); |
| } |
| else |
| { |
| voe::ScopedChannel sc(_channelManager, channel); |
| voe::Channel* channelPtr = sc.ChannelPtr(); |
| if (channelPtr == NULL) |
| { |
| _engineStatistics.SetLastError( |
| VE_CHANNEL_NOT_VALID, kTraceError, |
| "GetSpeechOutputLevelFullRange() failed to locate channel"); |
| return -1; |
| } |
| channelPtr->GetSpeechOutputLevelFullRange((WebRtc_UWord32&)level); |
| } |
| return 0; |
| } |
| |
| int VoEVolumeControlImpl::SetChannelOutputVolumeScaling(int channel, |
| float scaling) |
| { |
| WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_instanceId,-1), |
| "SetChannelOutputVolumeScaling(channel=%d, scaling=%3.2f)", |
| channel, scaling); |
| IPHONE_NOT_SUPPORTED(); |
| if (!_engineStatistics.Initialized()) |
| { |
| _engineStatistics.SetLastError(VE_NOT_INITED, kTraceError); |
| return -1; |
| } |
| if (scaling < kMinOutputVolumeScaling || |
| scaling > kMaxOutputVolumeScaling) |
| { |
| _engineStatistics.SetLastError( |
| VE_INVALID_ARGUMENT, kTraceError, |
| "SetChannelOutputVolumeScaling() invalid parameter"); |
| return -1; |
| } |
| voe::ScopedChannel sc(_channelManager, channel); |
| voe::Channel* channelPtr = sc.ChannelPtr(); |
| if (channelPtr == NULL) |
| { |
| _engineStatistics.SetLastError( |
| VE_CHANNEL_NOT_VALID, kTraceError, |
| "SetChannelOutputVolumeScaling() failed to locate channel"); |
| return -1; |
| } |
| return channelPtr->SetChannelOutputVolumeScaling(scaling); |
| } |
| |
| int VoEVolumeControlImpl::GetChannelOutputVolumeScaling(int channel, |
| float& scaling) |
| { |
| WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_instanceId,-1), |
| "GetChannelOutputVolumeScaling(channel=%d, scaling=?)", channel); |
| IPHONE_NOT_SUPPORTED(); |
| if (!_engineStatistics.Initialized()) |
| { |
| _engineStatistics.SetLastError(VE_NOT_INITED, kTraceError); |
| return -1; |
| } |
| voe::ScopedChannel sc(_channelManager, channel); |
| voe::Channel* channelPtr = sc.ChannelPtr(); |
| if (channelPtr == NULL) |
| { |
| _engineStatistics.SetLastError( |
| VE_CHANNEL_NOT_VALID, kTraceError, |
| "GetChannelOutputVolumeScaling() failed to locate channel"); |
| return -1; |
| } |
| return channelPtr->GetChannelOutputVolumeScaling(scaling); |
| } |
| |
| int VoEVolumeControlImpl::SetOutputVolumePan(int channel, |
| float left, |
| float right) |
| { |
| WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_instanceId,-1), |
| "SetOutputVolumePan(channel=%d, left=%2.1f, right=%2.1f)", |
| channel, left, right); |
| ANDROID_NOT_SUPPORTED(_engineStatistics); |
| IPHONE_NOT_SUPPORTED(); |
| |
| if (!_engineStatistics.Initialized()) |
| { |
| _engineStatistics.SetLastError(VE_NOT_INITED, kTraceError); |
| return -1; |
| } |
| |
| bool available(false); |
| _audioDevicePtr->StereoPlayoutIsAvailable(&available); |
| if (!available) |
| { |
| _engineStatistics.SetLastError( |
| VE_FUNC_NO_STEREO, kTraceError, |
| "SetOutputVolumePan() stereo playout not supported"); |
| return -1; |
| } |
| if ((left < kMinOutputVolumePanning) || |
| (left > kMaxOutputVolumePanning) || |
| (right < kMinOutputVolumePanning) || |
| (right > kMaxOutputVolumePanning)) |
| { |
| _engineStatistics.SetLastError( |
| VE_INVALID_ARGUMENT, kTraceError, |
| "SetOutputVolumePan() invalid parameter"); |
| return -1; |
| } |
| |
| if (channel == -1) |
| { |
| // Master balance (affectes the signal after output mixing) |
| return _outputMixerPtr->SetOutputVolumePan(left, right); |
| } |
| else |
| { |
| // Per-channel balance (affects the signal before output mixing) |
| voe::ScopedChannel sc(_channelManager, channel); |
| voe::Channel* channelPtr = sc.ChannelPtr(); |
| if (channelPtr == NULL) |
| { |
| _engineStatistics.SetLastError( |
| VE_CHANNEL_NOT_VALID, kTraceError, |
| "SetOutputVolumePan() failed to locate channel"); |
| return -1; |
| } |
| return channelPtr->SetOutputVolumePan(left, right); |
| } |
| return 0; |
| } |
| |
| int VoEVolumeControlImpl::GetOutputVolumePan(int channel, |
| float& left, |
| float& right) |
| { |
| WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_instanceId,-1), |
| "GetOutputVolumePan(channel=%d, left=?, right=?)", channel); |
| ANDROID_NOT_SUPPORTED(_engineStatistics); |
| IPHONE_NOT_SUPPORTED(); |
| |
| if (!_engineStatistics.Initialized()) |
| { |
| _engineStatistics.SetLastError(VE_NOT_INITED, kTraceError); |
| return -1; |
| } |
| |
| bool available(false); |
| _audioDevicePtr->StereoPlayoutIsAvailable(&available); |
| if (!available) |
| { |
| _engineStatistics.SetLastError( |
| VE_FUNC_NO_STEREO, kTraceError, |
| "GetOutputVolumePan() stereo playout not supported"); |
| return -1; |
| } |
| |
| if (channel == -1) |
| { |
| return _outputMixerPtr->GetOutputVolumePan(left, right); |
| } |
| else |
| { |
| voe::ScopedChannel sc(_channelManager, channel); |
| voe::Channel* channelPtr = sc.ChannelPtr(); |
| if (channelPtr == NULL) |
| { |
| _engineStatistics.SetLastError( |
| VE_CHANNEL_NOT_VALID, kTraceError, |
| "GetOutputVolumePan() failed to locate channel"); |
| return -1; |
| } |
| return channelPtr->GetOutputVolumePan(left, right); |
| } |
| return 0; |
| } |
| |
| #endif // #ifdef WEBRTC_VOICE_ENGINE_VOLUME_CONTROL_API |
| |
| } // namespace webrtc |