10e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org/*
20e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * libjingle
30e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * Copyright 2012, Google Inc.
40e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *
50e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * Redistribution and use in source and binary forms, with or without
60e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * modification, are permitted provided that the following conditions are met:
70e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *
80e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *  1. Redistributions of source code must retain the above copyright notice,
90e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *     this list of conditions and the following disclaimer.
100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *  2. Redistributions in binary form must reproduce the above copyright notice,
110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *     this list of conditions and the following disclaimer in the documentation
120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *     and/or other materials provided with the distribution.
130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *  3. The name of the author may not be used to endorse or promote products
140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *     derived from this software without specific prior written permission.
150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *
160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org */
270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include "talk/app/webrtc/dtmfsender.h"
290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include <ctype.h>
310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include <string>
330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
342a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org#include "webrtc/base/logging.h"
352a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org#include "webrtc/base/thread.h"
360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgnamespace webrtc {
380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgenum {
400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  MSG_DO_INSERT_DTMF = 0,
410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org};
420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// RFC4733
440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org//  +-------+--------+------+---------+
450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org//  | Event | Code   | Type | Volume? |
460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org//  +-------+--------+------+---------+
470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org//  | 0--9  | 0--9   | tone | yes     |
480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org//  | *     | 10     | tone | yes     |
490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org//  | #     | 11     | tone | yes     |
500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org//  | A--D  | 12--15 | tone | yes     |
510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org//  +-------+--------+------+---------+
520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// The "," is a special event defined by the WebRTC spec. It means to delay for
530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// 2 seconds before processing the next tone. We use -1 as its code.
540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgstatic const int kDtmfCodeTwoSecondDelay = -1;
550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgstatic const int kDtmfTwoSecondInMs = 2000;
560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgstatic const char kDtmfValidTones[] = ",0123456789*#ABCDabcd";
570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgstatic const char kDtmfTonesTable[] = ",0123456789*#ABCD";
580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// The duration cannot be more than 6000ms or less than 70ms. The gap between
590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// tones must be at least 50 ms.
600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgstatic const int kDtmfDefaultDurationMs = 100;
610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgstatic const int kDtmfMinDurationMs = 70;
620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgstatic const int kDtmfMaxDurationMs = 6000;
630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgstatic const int kDtmfDefaultGapMs = 50;
640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgstatic const int kDtmfMinGapMs = 50;
650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// Get DTMF code from the DTMF event character.
670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool GetDtmfCode(char tone, int* code) {
680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Convert a-d to A-D.
690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  char event = toupper(tone);
700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  const char* p = strchr(kDtmfTonesTable, event);
710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (!p) {
720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return false;
730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  *code = p - kDtmfTonesTable - 1;
750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return true;
760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
782a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.orgrtc::scoped_refptr<DtmfSender> DtmfSender::Create(
790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    AudioTrackInterface* track,
802a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org    rtc::Thread* signaling_thread,
810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    DtmfProviderInterface* provider) {
820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (!track || !signaling_thread) {
830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return NULL;
840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
852a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org  rtc::scoped_refptr<DtmfSender> dtmf_sender(
862a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org      new rtc::RefCountedObject<DtmfSender>(track, signaling_thread,
870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                                  provider));
880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return dtmf_sender;
890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgDtmfSender::DtmfSender(AudioTrackInterface* track,
922a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org                       rtc::Thread* signaling_thread,
930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                       DtmfProviderInterface* provider)
940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    : track_(track),
950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      observer_(NULL),
960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      signaling_thread_(signaling_thread),
970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      provider_(provider),
980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      duration_(kDtmfDefaultDurationMs),
990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      inter_tone_gap_(kDtmfDefaultGapMs) {
1000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ASSERT(track_ != NULL);
1010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ASSERT(signaling_thread_ != NULL);
1020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (provider_) {
1030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    ASSERT(provider_->GetOnDestroyedSignal() != NULL);
1040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    provider_->GetOnDestroyedSignal()->connect(
1050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        this, &DtmfSender::OnProviderDestroyed);
1060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
1070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
1080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgDtmfSender::~DtmfSender() {
1100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (provider_) {
1110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    ASSERT(provider_->GetOnDestroyedSignal() != NULL);
1120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    provider_->GetOnDestroyedSignal()->disconnect(this);
1130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
1140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  StopSending();
1150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
1160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid DtmfSender::RegisterObserver(DtmfSenderObserverInterface* observer) {
1180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  observer_ = observer;
1190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
1200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid DtmfSender::UnregisterObserver() {
1220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  observer_ = NULL;
1230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
1240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool DtmfSender::CanInsertDtmf() {
1260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ASSERT(signaling_thread_->IsCurrent());
1270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (!provider_) {
1280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return false;
1290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
1300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return provider_->CanInsertDtmf(track_->id());
1310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
1320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool DtmfSender::InsertDtmf(const std::string& tones, int duration,
1340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                            int inter_tone_gap) {
1350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ASSERT(signaling_thread_->IsCurrent());
1360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (duration > kDtmfMaxDurationMs ||
1380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      duration < kDtmfMinDurationMs ||
1390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      inter_tone_gap < kDtmfMinGapMs) {
1400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    LOG(LS_ERROR) << "InsertDtmf is called with invalid duration or tones gap. "
1410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        << "The duration cannot be more than " << kDtmfMaxDurationMs
1420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        << "ms or less than " << kDtmfMinDurationMs << "ms. "
1430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        << "The gap between tones must be at least " << kDtmfMinGapMs << "ms.";
1440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return false;
1450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
1460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (!CanInsertDtmf()) {
1480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    LOG(LS_ERROR)
1490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        << "InsertDtmf is called on DtmfSender that can't send DTMF.";
1500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return false;
1510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
1520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  tones_ = tones;
1540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  duration_ = duration;
1550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  inter_tone_gap_ = inter_tone_gap;
1560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Clear the previous queue.
1570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  signaling_thread_->Clear(this, MSG_DO_INSERT_DTMF);
1580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Kick off a new DTMF task queue.
1590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  signaling_thread_->Post(this, MSG_DO_INSERT_DTMF);
1600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return true;
1610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
1620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgconst AudioTrackInterface* DtmfSender::track() const {
1640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return track_;
1650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
1660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgstd::string DtmfSender::tones() const {
1680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return tones_;
1690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
1700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgint DtmfSender::duration() const {
1720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return duration_;
1730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
1740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgint DtmfSender::inter_tone_gap() const {
1760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return inter_tone_gap_;
1770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
1780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1792a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.orgvoid DtmfSender::OnMessage(rtc::Message* msg) {
1800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  switch (msg->message_id) {
1810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    case MSG_DO_INSERT_DTMF: {
1820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      DoInsertDtmf();
1830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      break;
1840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
1850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    default: {
1860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      ASSERT(false);
1870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      break;
1880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
1890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
1900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
1910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid DtmfSender::DoInsertDtmf() {
1930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ASSERT(signaling_thread_->IsCurrent());
1940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Get the first DTMF tone from the tone buffer. Unrecognized characters will
1960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // be ignored and skipped.
1970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  size_t first_tone_pos = tones_.find_first_of(kDtmfValidTones);
1980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  int code = 0;
1990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (first_tone_pos == std::string::npos) {
2000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    tones_.clear();
2010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    // Fire a “OnToneChange” event with an empty string and stop.
2020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (observer_) {
2030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      observer_->OnToneChange(std::string());
2040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
2050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return;
2060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  } else {
2070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    char tone = tones_[first_tone_pos];
2080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (!GetDtmfCode(tone, &code)) {
2090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      // The find_first_of(kDtmfValidTones) should have guarantee |tone| is
2100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      // a valid DTMF tone.
2110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      ASSERT(false);
2120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
2130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
2140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  int tone_gap = inter_tone_gap_;
2160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (code == kDtmfCodeTwoSecondDelay) {
2170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    // Special case defined by WebRTC - The character',' indicates a delay of 2
2180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    // seconds before processing the next character in the tones parameter.
2190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    tone_gap = kDtmfTwoSecondInMs;
2200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  } else {
2210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (!provider_) {
2220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      LOG(LS_ERROR) << "The DtmfProvider has been destroyed.";
2230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return;
2240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
2250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    // The provider starts playout of the given tone on the
2260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    // associated RTP media stream, using the appropriate codec.
2270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (!provider_->InsertDtmf(track_->id(), code, duration_)) {
2280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      LOG(LS_ERROR) << "The DtmfProvider can no longer send DTMF.";
2290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return;
2300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
2310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    // Wait for the number of milliseconds specified by |duration_|.
2320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    tone_gap += duration_;
2330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
2340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Fire a “OnToneChange” event with the tone that's just processed.
2360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (observer_) {
2370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    observer_->OnToneChange(tones_.substr(first_tone_pos, 1));
2380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
2390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Erase the unrecognized characters plus the tone that's just processed.
2410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  tones_.erase(0, first_tone_pos + 1);
2420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Continue with the next tone.
2440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  signaling_thread_->PostDelayed(tone_gap, this, MSG_DO_INSERT_DTMF);
2450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
2460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid DtmfSender::OnProviderDestroyed() {
2480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  LOG(LS_INFO) << "The Dtmf provider is deleted. Clear the sending queue.";
2490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  StopSending();
2500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  provider_ = NULL;
2510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
2520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid DtmfSender::StopSending() {
2540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  signaling_thread_->Clear(this);
2550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
2560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}  // namespace webrtc
258