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