1470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com/*
29a065d1eae9ed296e1e2eaaad73d7ca1223bfe79mflodman@webrtc.org *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
3470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com *
4470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com *  Use of this source code is governed by a BSD-style license
5470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com *  that can be found in the LICENSE file in the root of the source
6470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com *  tree. An additional intellectual property rights grant can be found
7470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com *  in the file PATENTS.  All contributing project authors may
8470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com *  be found in the AUTHORS file in the root of the source tree.
9470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com */
10470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
11b7edd065306329309dac6767fe4914c185f941f8turaj@webrtc.org#include "webrtc/voice_engine/voe_dtmf_impl.h"
12470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1398f53510b222f71fdd8b799b2f33737ceeb28c61Henrik Kjellander#include "webrtc/system_wrappers/include/critical_section_wrapper.h"
1498f53510b222f71fdd8b799b2f33737ceeb28c61Henrik Kjellander#include "webrtc/system_wrappers/include/trace.h"
15b7edd065306329309dac6767fe4914c185f941f8turaj@webrtc.org#include "webrtc/voice_engine/channel.h"
16b7edd065306329309dac6767fe4914c185f941f8turaj@webrtc.org#include "webrtc/voice_engine/include/voe_errors.h"
17b7edd065306329309dac6767fe4914c185f941f8turaj@webrtc.org#include "webrtc/voice_engine/output_mixer.h"
18b7edd065306329309dac6767fe4914c185f941f8turaj@webrtc.org#include "webrtc/voice_engine/transmit_mixer.h"
19b7edd065306329309dac6767fe4914c185f941f8turaj@webrtc.org#include "webrtc/voice_engine/voice_engine_impl.h"
20470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
21470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comnamespace webrtc {
22470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
230d266054acece70259fc1e85026194154f41e5a0Jelena MarusicVoEDtmf* VoEDtmf::GetInterface(VoiceEngine* voiceEngine) {
24470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#ifndef WEBRTC_VOICE_ENGINE_DTMF_API
250d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  return NULL;
26470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#else
270d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  if (NULL == voiceEngine) {
280d266054acece70259fc1e85026194154f41e5a0Jelena Marusic    return NULL;
290d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  }
300d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  VoiceEngineImpl* s = static_cast<VoiceEngineImpl*>(voiceEngine);
310d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  s->AddRef();
320d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  return s;
33470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#endif
34470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
35470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
36470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#ifdef WEBRTC_VOICE_ENGINE_DTMF_API
37470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
380d266054acece70259fc1e85026194154f41e5a0Jelena MarusicVoEDtmfImpl::VoEDtmfImpl(voe::SharedData* shared)
390d266054acece70259fc1e85026194154f41e5a0Jelena Marusic    : _dtmfFeedback(true), _dtmfDirectFeedback(false), _shared(shared) {
400d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  WEBRTC_TRACE(kTraceMemory, kTraceVoice, VoEId(_shared->instance_id(), -1),
410d266054acece70259fc1e85026194154f41e5a0Jelena Marusic               "VoEDtmfImpl::VoEDtmfImpl() - ctor");
42470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
43470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
440d266054acece70259fc1e85026194154f41e5a0Jelena MarusicVoEDtmfImpl::~VoEDtmfImpl() {
450d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  WEBRTC_TRACE(kTraceMemory, kTraceVoice, VoEId(_shared->instance_id(), -1),
460d266054acece70259fc1e85026194154f41e5a0Jelena Marusic               "VoEDtmfImpl::~VoEDtmfImpl() - dtor");
47470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
48470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
49470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint VoEDtmfImpl::SendTelephoneEvent(int channel,
50f81f9f8c2a18fb20ee60406ece45ff3210367ff9andrew@webrtc.org                                    int eventCode,
51470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                    bool outOfBand,
52470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                    int lengthMs,
530d266054acece70259fc1e85026194154f41e5a0Jelena Marusic                                    int attenuationDb) {
540d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
550d266054acece70259fc1e85026194154f41e5a0Jelena Marusic               "SendTelephoneEvent(channel=%d, eventCode=%d, outOfBand=%d,"
560d266054acece70259fc1e85026194154f41e5a0Jelena Marusic               "length=%d, attenuationDb=%d)",
570d266054acece70259fc1e85026194154f41e5a0Jelena Marusic               channel, eventCode, (int)outOfBand, lengthMs, attenuationDb);
580d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  if (!_shared->statistics().Initialized()) {
590d266054acece70259fc1e85026194154f41e5a0Jelena Marusic    _shared->SetLastError(VE_NOT_INITED, kTraceError);
600d266054acece70259fc1e85026194154f41e5a0Jelena Marusic    return -1;
610d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  }
620d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
630d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  voe::Channel* channelPtr = ch.channel();
640d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  if (channelPtr == NULL) {
650d266054acece70259fc1e85026194154f41e5a0Jelena Marusic    _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
660d266054acece70259fc1e85026194154f41e5a0Jelena Marusic                          "SendTelephoneEvent() failed to locate channel");
670d266054acece70259fc1e85026194154f41e5a0Jelena Marusic    return -1;
680d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  }
690d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  if (!channelPtr->Sending()) {
700d266054acece70259fc1e85026194154f41e5a0Jelena Marusic    _shared->SetLastError(VE_NOT_SENDING, kTraceError,
710d266054acece70259fc1e85026194154f41e5a0Jelena Marusic                          "SendTelephoneEvent() sending is not active");
720d266054acece70259fc1e85026194154f41e5a0Jelena Marusic    return -1;
730d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  }
740d266054acece70259fc1e85026194154f41e5a0Jelena Marusic
750d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  // Sanity check
760d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  const int maxEventCode = outOfBand ? static_cast<int>(kMaxTelephoneEventCode)
770d266054acece70259fc1e85026194154f41e5a0Jelena Marusic                                     : static_cast<int>(kMaxDtmfEventCode);
780d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  const bool testFailed = ((eventCode < 0) || (eventCode > maxEventCode) ||
790d266054acece70259fc1e85026194154f41e5a0Jelena Marusic                           (lengthMs < kMinTelephoneEventDuration) ||
800d266054acece70259fc1e85026194154f41e5a0Jelena Marusic                           (lengthMs > kMaxTelephoneEventDuration) ||
810d266054acece70259fc1e85026194154f41e5a0Jelena Marusic                           (attenuationDb < kMinTelephoneEventAttenuation) ||
820d266054acece70259fc1e85026194154f41e5a0Jelena Marusic                           (attenuationDb > kMaxTelephoneEventAttenuation));
830d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  if (testFailed) {
840d266054acece70259fc1e85026194154f41e5a0Jelena Marusic    _shared->SetLastError(VE_INVALID_ARGUMENT, kTraceError,
850d266054acece70259fc1e85026194154f41e5a0Jelena Marusic                          "SendTelephoneEvent() invalid parameter(s)");
860d266054acece70259fc1e85026194154f41e5a0Jelena Marusic    return -1;
870d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  }
880d266054acece70259fc1e85026194154f41e5a0Jelena Marusic
890d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  const bool isDtmf = (eventCode >= 0) && (eventCode <= kMaxDtmfEventCode);
900d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  const bool playDtmfToneDirect =
910d266054acece70259fc1e85026194154f41e5a0Jelena Marusic      isDtmf && (_dtmfFeedback && _dtmfDirectFeedback);
920d266054acece70259fc1e85026194154f41e5a0Jelena Marusic
930d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  if (playDtmfToneDirect) {
940d266054acece70259fc1e85026194154f41e5a0Jelena Marusic    // Mute the microphone signal while playing back the tone directly.
950d266054acece70259fc1e85026194154f41e5a0Jelena Marusic    // This is to reduce the risk of introducing echo from the added output.
960d266054acece70259fc1e85026194154f41e5a0Jelena Marusic    _shared->transmit_mixer()->UpdateMuteMicrophoneTime(lengthMs);
970d266054acece70259fc1e85026194154f41e5a0Jelena Marusic
980d266054acece70259fc1e85026194154f41e5a0Jelena Marusic    // Play out local feedback tone directly (same approach for both inband
990d266054acece70259fc1e85026194154f41e5a0Jelena Marusic    // and outband).
1000d266054acece70259fc1e85026194154f41e5a0Jelena Marusic    // Reduce the length of the the tone with 80ms to reduce risk of echo.
1010d266054acece70259fc1e85026194154f41e5a0Jelena Marusic    // For non-direct feedback, outband and inband cases are handled
1020d266054acece70259fc1e85026194154f41e5a0Jelena Marusic    // differently.
1030d266054acece70259fc1e85026194154f41e5a0Jelena Marusic    _shared->output_mixer()->PlayDtmfTone(eventCode, lengthMs - 80,
1040d266054acece70259fc1e85026194154f41e5a0Jelena Marusic                                          attenuationDb);
1050d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  }
1060d266054acece70259fc1e85026194154f41e5a0Jelena Marusic
1070d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  if (outOfBand) {
1080d266054acece70259fc1e85026194154f41e5a0Jelena Marusic    // The RTP/RTCP module will always deliver OnPlayTelephoneEvent when
1090d266054acece70259fc1e85026194154f41e5a0Jelena Marusic    // an event is transmitted. It is up to the VoE to utilize it or not.
1100d266054acece70259fc1e85026194154f41e5a0Jelena Marusic    // This flag ensures that feedback/playout is enabled; however, the
1110d266054acece70259fc1e85026194154f41e5a0Jelena Marusic    // channel object must still parse out the Dtmf events (0-15) from
1120d266054acece70259fc1e85026194154f41e5a0Jelena Marusic    // all possible events (0-255).
1130d266054acece70259fc1e85026194154f41e5a0Jelena Marusic    const bool playDTFMEvent = (_dtmfFeedback && !_dtmfDirectFeedback);
1140d266054acece70259fc1e85026194154f41e5a0Jelena Marusic
1150d266054acece70259fc1e85026194154f41e5a0Jelena Marusic    return channelPtr->SendTelephoneEventOutband(eventCode, lengthMs,
1160d266054acece70259fc1e85026194154f41e5a0Jelena Marusic                                                 attenuationDb, playDTFMEvent);
1170d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  } else {
1180d266054acece70259fc1e85026194154f41e5a0Jelena Marusic    // For Dtmf tones, we want to ensure that inband tones are played out
1190d266054acece70259fc1e85026194154f41e5a0Jelena Marusic    // in sync with the transmitted audio. This flag is utilized by the
1200d266054acece70259fc1e85026194154f41e5a0Jelena Marusic    // channel object to determine if the queued Dtmf e vent shall also
1210d266054acece70259fc1e85026194154f41e5a0Jelena Marusic    // be fed to the output mixer in the same step as input audio is
1220d266054acece70259fc1e85026194154f41e5a0Jelena Marusic    // replaced by inband Dtmf tones.
1230d266054acece70259fc1e85026194154f41e5a0Jelena Marusic    const bool playDTFMEvent =
1240d266054acece70259fc1e85026194154f41e5a0Jelena Marusic        (isDtmf && _dtmfFeedback && !_dtmfDirectFeedback);
1250d266054acece70259fc1e85026194154f41e5a0Jelena Marusic
1260d266054acece70259fc1e85026194154f41e5a0Jelena Marusic    return channelPtr->SendTelephoneEventInband(eventCode, lengthMs,
1270d266054acece70259fc1e85026194154f41e5a0Jelena Marusic                                                attenuationDb, playDTFMEvent);
1280d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  }
129470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
130470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
131470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint VoEDtmfImpl::SetSendTelephoneEventPayloadType(int channel,
1320d266054acece70259fc1e85026194154f41e5a0Jelena Marusic                                                  unsigned char type) {
1330d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
1340d266054acece70259fc1e85026194154f41e5a0Jelena Marusic               "SetSendTelephoneEventPayloadType(channel=%d, type=%u)", channel,
1350d266054acece70259fc1e85026194154f41e5a0Jelena Marusic               type);
1360d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  if (!_shared->statistics().Initialized()) {
1370d266054acece70259fc1e85026194154f41e5a0Jelena Marusic    _shared->SetLastError(VE_NOT_INITED, kTraceError);
1380d266054acece70259fc1e85026194154f41e5a0Jelena Marusic    return -1;
1390d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  }
1400d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
1410d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  voe::Channel* channelPtr = ch.channel();
1420d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  if (channelPtr == NULL) {
1430d266054acece70259fc1e85026194154f41e5a0Jelena Marusic    _shared->SetLastError(
1440d266054acece70259fc1e85026194154f41e5a0Jelena Marusic        VE_CHANNEL_NOT_VALID, kTraceError,
1450d266054acece70259fc1e85026194154f41e5a0Jelena Marusic        "SetSendTelephoneEventPayloadType() failed to locate channel");
1460d266054acece70259fc1e85026194154f41e5a0Jelena Marusic    return -1;
1470d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  }
1480d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  return channelPtr->SetSendTelephoneEventPayloadType(type);
149470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
150470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
151470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint VoEDtmfImpl::GetSendTelephoneEventPayloadType(int channel,
1520d266054acece70259fc1e85026194154f41e5a0Jelena Marusic                                                  unsigned char& type) {
1530d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  if (!_shared->statistics().Initialized()) {
1540d266054acece70259fc1e85026194154f41e5a0Jelena Marusic    _shared->SetLastError(VE_NOT_INITED, kTraceError);
1550d266054acece70259fc1e85026194154f41e5a0Jelena Marusic    return -1;
1560d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  }
1570d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
1580d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  voe::Channel* channelPtr = ch.channel();
1590d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  if (channelPtr == NULL) {
1600d266054acece70259fc1e85026194154f41e5a0Jelena Marusic    _shared->SetLastError(
1610d266054acece70259fc1e85026194154f41e5a0Jelena Marusic        VE_CHANNEL_NOT_VALID, kTraceError,
1620d266054acece70259fc1e85026194154f41e5a0Jelena Marusic        "GetSendTelephoneEventPayloadType() failed to locate channel");
1630d266054acece70259fc1e85026194154f41e5a0Jelena Marusic    return -1;
1640d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  }
1650d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  return channelPtr->GetSendTelephoneEventPayloadType(type);
166470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
167470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1680d266054acece70259fc1e85026194154f41e5a0Jelena Marusicint VoEDtmfImpl::PlayDtmfTone(int eventCode, int lengthMs, int attenuationDb) {
1690d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
1700d266054acece70259fc1e85026194154f41e5a0Jelena Marusic               "PlayDtmfTone(eventCode=%d, lengthMs=%d, attenuationDb=%d)",
1710d266054acece70259fc1e85026194154f41e5a0Jelena Marusic               eventCode, lengthMs, attenuationDb);
1720d266054acece70259fc1e85026194154f41e5a0Jelena Marusic
1730d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  if (!_shared->statistics().Initialized()) {
1740d266054acece70259fc1e85026194154f41e5a0Jelena Marusic    _shared->SetLastError(VE_NOT_INITED, kTraceError);
1750d266054acece70259fc1e85026194154f41e5a0Jelena Marusic    return -1;
1760d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  }
1770d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  if (!_shared->audio_device()->Playing()) {
1780d266054acece70259fc1e85026194154f41e5a0Jelena Marusic    _shared->SetLastError(VE_NOT_PLAYING, kTraceError,
1790d266054acece70259fc1e85026194154f41e5a0Jelena Marusic                          "PlayDtmfTone() no channel is playing out");
1800d266054acece70259fc1e85026194154f41e5a0Jelena Marusic    return -1;
1810d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  }
1820d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  if ((eventCode < kMinDtmfEventCode) || (eventCode > kMaxDtmfEventCode) ||
1830d266054acece70259fc1e85026194154f41e5a0Jelena Marusic      (lengthMs < kMinTelephoneEventDuration) ||
1840d266054acece70259fc1e85026194154f41e5a0Jelena Marusic      (lengthMs > kMaxTelephoneEventDuration) ||
1850d266054acece70259fc1e85026194154f41e5a0Jelena Marusic      (attenuationDb < kMinTelephoneEventAttenuation) ||
1860d266054acece70259fc1e85026194154f41e5a0Jelena Marusic      (attenuationDb > kMaxTelephoneEventAttenuation)) {
1870d266054acece70259fc1e85026194154f41e5a0Jelena Marusic    _shared->SetLastError(VE_INVALID_ARGUMENT, kTraceError,
1880d266054acece70259fc1e85026194154f41e5a0Jelena Marusic                          "PlayDtmfTone() invalid tone parameter(s)");
1890d266054acece70259fc1e85026194154f41e5a0Jelena Marusic    return -1;
1900d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  }
1910d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  return _shared->output_mixer()->PlayDtmfTone(eventCode, lengthMs,
192851becd00ce814f0e02a5c5a56ac0322a7f9494dtommi@webrtc.org                                               attenuationDb);
193470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
194470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1950d266054acece70259fc1e85026194154f41e5a0Jelena Marusicint VoEDtmfImpl::SetDtmfFeedbackStatus(bool enable, bool directFeedback) {
1960d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
1970d266054acece70259fc1e85026194154f41e5a0Jelena Marusic               "SetDtmfFeedbackStatus(enable=%d, directFeeback=%d)",
1980d266054acece70259fc1e85026194154f41e5a0Jelena Marusic               (int)enable, (int)directFeedback);
199470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2000d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  CriticalSectionScoped sc(_shared->crit_sec());
201470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2020d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  _dtmfFeedback = enable;
2030d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  _dtmfDirectFeedback = directFeedback;
204470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2050d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  return 0;
206470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
207470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2080d266054acece70259fc1e85026194154f41e5a0Jelena Marusicint VoEDtmfImpl::GetDtmfFeedbackStatus(bool& enabled, bool& directFeedback) {
2090d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  CriticalSectionScoped sc(_shared->crit_sec());
210470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2110d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  enabled = _dtmfFeedback;
2120d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  directFeedback = _dtmfDirectFeedback;
2130d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  return 0;
214470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
215470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#endif  // #ifdef WEBRTC_VOICE_ENGINE_DTMF_API
216470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
217470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}  // namespace webrtc
218