2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
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.
11 #include "webrtc/voice_engine/voe_volume_control_impl.h"
13 #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"
23 VoEVolumeControl* VoEVolumeControl::GetInterface(VoiceEngine* voiceEngine)
25 #ifndef WEBRTC_VOICE_ENGINE_VOLUME_CONTROL_API
28 if (NULL == voiceEngine)
32 VoiceEngineImpl* s = static_cast<VoiceEngineImpl*>(voiceEngine);
38 #ifdef WEBRTC_VOICE_ENGINE_VOLUME_CONTROL_API
40 VoEVolumeControlImpl::VoEVolumeControlImpl(voe::SharedData* shared)
43 WEBRTC_TRACE(kTraceMemory, kTraceVoice, VoEId(_shared->instance_id(), -1),
44 "VoEVolumeControlImpl::VoEVolumeControlImpl() - ctor");
47 VoEVolumeControlImpl::~VoEVolumeControlImpl()
49 WEBRTC_TRACE(kTraceMemory, kTraceVoice, VoEId(_shared->instance_id(), -1),
50 "VoEVolumeControlImpl::~VoEVolumeControlImpl() - dtor");
53 int VoEVolumeControlImpl::SetSpeakerVolume(unsigned int volume)
55 WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
56 "SetSpeakerVolume(volume=%u)", volume);
58 if (!_shared->statistics().Initialized())
60 _shared->SetLastError(VE_NOT_INITED, kTraceError);
63 if (volume > kMaxVolumeLevel)
65 _shared->SetLastError(VE_INVALID_ARGUMENT, kTraceError,
66 "SetSpeakerVolume() invalid argument");
73 // scale: [0,kMaxVolumeLevel] -> [0,MaxSpeakerVolume]
74 if (_shared->audio_device()->MaxSpeakerVolume(&maxVol) != 0)
76 _shared->SetLastError(VE_MIC_VOL_ERROR, kTraceError,
77 "SetSpeakerVolume() failed to get max volume");
80 // Round the value and avoid floating computation.
81 spkrVol = (uint32_t)((volume * maxVol +
82 (int)(kMaxVolumeLevel / 2)) / (kMaxVolumeLevel));
84 // set the actual volume using the audio mixer
85 if (_shared->audio_device()->SetSpeakerVolume(spkrVol) != 0)
87 _shared->SetLastError(VE_MIC_VOL_ERROR, kTraceError,
88 "SetSpeakerVolume() failed to set speaker volume");
94 int VoEVolumeControlImpl::GetSpeakerVolume(unsigned int& volume)
96 WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
97 "GetSpeakerVolume()");
99 if (!_shared->statistics().Initialized())
101 _shared->SetLastError(VE_NOT_INITED, kTraceError);
108 if (_shared->audio_device()->SpeakerVolume(&spkrVol) != 0)
110 _shared->SetLastError(VE_GET_MIC_VOL_ERROR, kTraceError,
111 "GetSpeakerVolume() unable to get speaker volume");
115 // scale: [0, MaxSpeakerVolume] -> [0, kMaxVolumeLevel]
116 if (_shared->audio_device()->MaxSpeakerVolume(&maxVol) != 0)
118 _shared->SetLastError(VE_GET_MIC_VOL_ERROR, kTraceError,
119 "GetSpeakerVolume() unable to get max speaker volume");
122 // Round the value and avoid floating computation.
123 volume = (uint32_t) ((spkrVol * kMaxVolumeLevel +
124 (int)(maxVol / 2)) / (maxVol));
126 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
127 VoEId(_shared->instance_id(), -1),
128 "GetSpeakerVolume() => volume=%d", volume);
132 int VoEVolumeControlImpl::SetSystemOutputMute(bool enable)
134 WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
135 "GetSystemOutputMute(enabled=%d)", enable);
137 if (!_shared->statistics().Initialized())
139 _shared->SetLastError(VE_NOT_INITED, kTraceError);
143 if (_shared->audio_device()->SetSpeakerMute(enable) != 0)
145 _shared->SetLastError(VE_GET_MIC_VOL_ERROR, kTraceError,
146 "SpeakerMute() unable to Set speaker mute");
153 int VoEVolumeControlImpl::GetSystemOutputMute(bool& enabled)
155 WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
156 "GetSystemOutputMute(enabled=?)");
158 if (!_shared->statistics().Initialized())
160 _shared->SetLastError(VE_NOT_INITED, kTraceError);
164 if (_shared->audio_device()->SpeakerMute(&enabled) != 0)
166 _shared->SetLastError(VE_GET_MIC_VOL_ERROR, kTraceError,
167 "SpeakerMute() unable to get speaker mute state");
170 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
171 VoEId(_shared->instance_id(), -1),
172 "GetSystemOutputMute() => %d", enabled);
176 int VoEVolumeControlImpl::SetMicVolume(unsigned int volume)
178 WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
179 "SetMicVolume(volume=%u)", volume);
181 if (!_shared->statistics().Initialized())
183 _shared->SetLastError(VE_NOT_INITED, kTraceError);
186 if (volume > kMaxVolumeLevel)
188 _shared->SetLastError(VE_INVALID_ARGUMENT, kTraceError,
189 "SetMicVolume() invalid argument");
196 // scale: [0, kMaxVolumeLevel] -> [0,MaxMicrophoneVolume]
197 if (_shared->audio_device()->MaxMicrophoneVolume(&maxVol) != 0)
199 _shared->SetLastError(VE_MIC_VOL_ERROR, kTraceError,
200 "SetMicVolume() failed to get max volume");
204 if (volume == kMaxVolumeLevel) {
205 // On Linux running pulse, users are able to set the volume above 100%
206 // through the volume control panel, where the +100% range is digital
207 // scaling. WebRTC does not support setting the volume above 100%, and
208 // simply ignores changing the volume if the user tries to set it to
209 // |kMaxVolumeLevel| while the current volume is higher than |maxVol|.
210 if (_shared->audio_device()->MicrophoneVolume(&micVol) != 0) {
211 _shared->SetLastError(VE_GET_MIC_VOL_ERROR, kTraceError,
212 "SetMicVolume() unable to get microphone volume");
215 if (micVol >= maxVol)
219 // Round the value and avoid floating point computation.
220 micVol = (uint32_t) ((volume * maxVol +
221 (int)(kMaxVolumeLevel / 2)) / (kMaxVolumeLevel));
223 // set the actual volume using the audio mixer
224 if (_shared->audio_device()->SetMicrophoneVolume(micVol) != 0)
226 _shared->SetLastError(VE_MIC_VOL_ERROR, kTraceError,
227 "SetMicVolume() failed to set mic volume");
233 int VoEVolumeControlImpl::GetMicVolume(unsigned int& volume)
235 WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
238 if (!_shared->statistics().Initialized())
240 _shared->SetLastError(VE_NOT_INITED, kTraceError);
247 if (_shared->audio_device()->MicrophoneVolume(&micVol) != 0)
249 _shared->SetLastError(VE_GET_MIC_VOL_ERROR, kTraceError,
250 "GetMicVolume() unable to get microphone volume");
254 // scale: [0, MaxMicrophoneVolume] -> [0, kMaxVolumeLevel]
255 if (_shared->audio_device()->MaxMicrophoneVolume(&maxVol) != 0)
257 _shared->SetLastError(VE_GET_MIC_VOL_ERROR, kTraceError,
258 "GetMicVolume() unable to get max microphone volume");
261 if (micVol < maxVol) {
262 // Round the value and avoid floating point calculation.
263 volume = (uint32_t) ((micVol * kMaxVolumeLevel +
264 (int)(maxVol / 2)) / (maxVol));
266 // Truncate the value to the kMaxVolumeLevel.
267 volume = kMaxVolumeLevel;
270 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
271 VoEId(_shared->instance_id(), -1),
272 "GetMicVolume() => volume=%d", volume);
276 int VoEVolumeControlImpl::SetInputMute(int channel, bool enable)
278 WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
279 "SetInputMute(channel=%d, enable=%d)", channel, enable);
281 if (!_shared->statistics().Initialized())
283 _shared->SetLastError(VE_NOT_INITED, kTraceError);
288 // Mute before demultiplexing <=> affects all channels
289 return _shared->transmit_mixer()->SetMute(enable);
291 // Mute after demultiplexing <=> affects one channel only
292 voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
293 voe::Channel* channelPtr = ch.channel();
294 if (channelPtr == NULL)
296 _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
297 "SetInputMute() failed to locate channel");
300 return channelPtr->SetMute(enable);
303 int VoEVolumeControlImpl::GetInputMute(int channel, bool& enabled)
305 WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
306 "GetInputMute(channel=%d)", channel);
308 if (!_shared->statistics().Initialized())
310 _shared->SetLastError(VE_NOT_INITED, kTraceError);
315 enabled = _shared->transmit_mixer()->Mute();
319 voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
320 voe::Channel* channelPtr = ch.channel();
321 if (channelPtr == NULL)
323 _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
324 "SetInputMute() failed to locate channel");
327 enabled = channelPtr->Mute();
329 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
330 VoEId(_shared->instance_id(), -1),
331 "GetInputMute() => enabled = %d", (int)enabled);
335 int VoEVolumeControlImpl::SetSystemInputMute(bool enable)
337 WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
338 "SetSystemInputMute(enabled=%d)", enable);
340 if (!_shared->statistics().Initialized())
342 _shared->SetLastError(VE_NOT_INITED, kTraceError);
346 if (_shared->audio_device()->SetMicrophoneMute(enable) != 0)
348 _shared->SetLastError(VE_GET_MIC_VOL_ERROR, kTraceError,
349 "MicrophoneMute() unable to set microphone mute state");
356 int VoEVolumeControlImpl::GetSystemInputMute(bool& enabled)
358 WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
359 "GetSystemInputMute(enabled=?)");
361 if (!_shared->statistics().Initialized())
363 _shared->SetLastError(VE_NOT_INITED, kTraceError);
367 if (_shared->audio_device()->MicrophoneMute(&enabled) != 0)
369 _shared->SetLastError(VE_GET_MIC_VOL_ERROR, kTraceError,
370 "MicrophoneMute() unable to get microphone mute state");
373 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
374 VoEId(_shared->instance_id(), -1),
375 "GetSystemInputMute() => %d", enabled);
379 int VoEVolumeControlImpl::GetSpeechInputLevel(unsigned int& level)
381 WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
382 "GetSpeechInputLevel()");
384 if (!_shared->statistics().Initialized())
386 _shared->SetLastError(VE_NOT_INITED, kTraceError);
389 int8_t currentLevel = _shared->transmit_mixer()->AudioLevel();
390 level = static_cast<unsigned int> (currentLevel);
391 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
392 VoEId(_shared->instance_id(), -1),
393 "GetSpeechInputLevel() => %d", level);
397 int VoEVolumeControlImpl::GetSpeechOutputLevel(int channel,
400 WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
401 "GetSpeechOutputLevel(channel=%d, level=?)", channel);
403 if (!_shared->statistics().Initialized())
405 _shared->SetLastError(VE_NOT_INITED, kTraceError);
410 return _shared->output_mixer()->GetSpeechOutputLevel(
415 voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
416 voe::Channel* channelPtr = ch.channel();
417 if (channelPtr == NULL)
419 _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
420 "GetSpeechOutputLevel() failed to locate channel");
423 channelPtr->GetSpeechOutputLevel((uint32_t&)level);
428 int VoEVolumeControlImpl::GetSpeechInputLevelFullRange(unsigned int& level)
430 WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
431 "GetSpeechInputLevelFullRange(level=?)");
433 if (!_shared->statistics().Initialized())
435 _shared->SetLastError(VE_NOT_INITED, kTraceError);
438 int16_t currentLevel = _shared->transmit_mixer()->
439 AudioLevelFullRange();
440 level = static_cast<unsigned int> (currentLevel);
441 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
442 VoEId(_shared->instance_id(), -1),
443 "GetSpeechInputLevelFullRange() => %d", level);
447 int VoEVolumeControlImpl::GetSpeechOutputLevelFullRange(int channel,
450 WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
451 "GetSpeechOutputLevelFullRange(channel=%d, level=?)", channel);
453 if (!_shared->statistics().Initialized())
455 _shared->SetLastError(VE_NOT_INITED, kTraceError);
460 return _shared->output_mixer()->GetSpeechOutputLevelFullRange(
465 voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
466 voe::Channel* channelPtr = ch.channel();
467 if (channelPtr == NULL)
469 _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
470 "GetSpeechOutputLevelFullRange() failed to locate channel");
473 channelPtr->GetSpeechOutputLevelFullRange((uint32_t&)level);
478 int VoEVolumeControlImpl::SetChannelOutputVolumeScaling(int channel,
481 WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
482 "SetChannelOutputVolumeScaling(channel=%d, scaling=%3.2f)",
484 if (!_shared->statistics().Initialized())
486 _shared->SetLastError(VE_NOT_INITED, kTraceError);
489 if (scaling < kMinOutputVolumeScaling ||
490 scaling > kMaxOutputVolumeScaling)
492 _shared->SetLastError(VE_INVALID_ARGUMENT, kTraceError,
493 "SetChannelOutputVolumeScaling() invalid parameter");
496 voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
497 voe::Channel* channelPtr = ch.channel();
498 if (channelPtr == NULL)
500 _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
501 "SetChannelOutputVolumeScaling() failed to locate channel");
504 return channelPtr->SetChannelOutputVolumeScaling(scaling);
507 int VoEVolumeControlImpl::GetChannelOutputVolumeScaling(int channel,
510 WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
511 "GetChannelOutputVolumeScaling(channel=%d, scaling=?)", channel);
512 if (!_shared->statistics().Initialized())
514 _shared->SetLastError(VE_NOT_INITED, kTraceError);
517 voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
518 voe::Channel* channelPtr = ch.channel();
519 if (channelPtr == NULL)
521 _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
522 "GetChannelOutputVolumeScaling() failed to locate channel");
525 return channelPtr->GetChannelOutputVolumeScaling(scaling);
528 int VoEVolumeControlImpl::SetOutputVolumePan(int channel,
532 WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
533 "SetOutputVolumePan(channel=%d, left=%2.1f, right=%2.1f)",
534 channel, left, right);
536 if (!_shared->statistics().Initialized())
538 _shared->SetLastError(VE_NOT_INITED, kTraceError);
542 bool available(false);
543 _shared->audio_device()->StereoPlayoutIsAvailable(&available);
546 _shared->SetLastError(VE_FUNC_NO_STEREO, kTraceError,
547 "SetOutputVolumePan() stereo playout not supported");
550 if ((left < kMinOutputVolumePanning) ||
551 (left > kMaxOutputVolumePanning) ||
552 (right < kMinOutputVolumePanning) ||
553 (right > kMaxOutputVolumePanning))
555 _shared->SetLastError(VE_INVALID_ARGUMENT, kTraceError,
556 "SetOutputVolumePan() invalid parameter");
562 // Master balance (affectes the signal after output mixing)
563 return _shared->output_mixer()->SetOutputVolumePan(left, right);
565 // Per-channel balance (affects the signal before output mixing)
566 voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
567 voe::Channel* channelPtr = ch.channel();
568 if (channelPtr == NULL)
570 _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
571 "SetOutputVolumePan() failed to locate channel");
574 return channelPtr->SetOutputVolumePan(left, right);
577 int VoEVolumeControlImpl::GetOutputVolumePan(int channel,
581 WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
582 "GetOutputVolumePan(channel=%d, left=?, right=?)", channel);
584 if (!_shared->statistics().Initialized())
586 _shared->SetLastError(VE_NOT_INITED, kTraceError);
590 bool available(false);
591 _shared->audio_device()->StereoPlayoutIsAvailable(&available);
594 _shared->SetLastError(VE_FUNC_NO_STEREO, kTraceError,
595 "GetOutputVolumePan() stereo playout not supported");
601 return _shared->output_mixer()->GetOutputVolumePan(left, right);
603 voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
604 voe::Channel* channelPtr = ch.channel();
605 if (channelPtr == NULL)
607 _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
608 "GetOutputVolumePan() failed to locate channel");
611 return channelPtr->GetOutputVolumePan(left, right);
614 #endif // #ifdef WEBRTC_VOICE_ENGINE_VOLUME_CONTROL_API
616 } // namespace webrtc