multimediacommscontroller/mmccdtmfpayloadformat/src/dtmfpayloadformatwrite.cpp
changeset 0 1bce908db942
equal deleted inserted replaced
-1:000000000000 0:1bce908db942
       
     1 /*
       
     2 * Copyright (c) 2006-2008 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:    Contains functionality for DTMF digit encoding and sending.
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 
       
    20 
       
    21 // INCLUDES
       
    22 #include <hal.h>
       
    23 #include "mmccnetworksettings.h"
       
    24 #include "dtmfpayloadformatwrite.h"
       
    25 #include "dtmfpayloadencoder.h"
       
    26 #include "dtmfeventpayloadinfo.h"
       
    27 #include "dtmftonepayloadinfo.h"
       
    28 #include "mccrtpdatasink.h"
       
    29 #include "mccinternaldef.h"
       
    30 #include "rtpdatasink.h"
       
    31 #include "mccrtpmediaclock.h"
       
    32 #include "mccinternalevents.h"
       
    33 #include "dtmfhighresolutiontimer.h"
       
    34 
       
    35 // CONSTANTS
       
    36 const TUint8 KValidDTMFDigits[] = { '0', '1', '2', '3', '4', '5', '6', '7', 
       
    37     '8', '9', 'a', 'b', 'c', 'd', 'A', 'B', 'C', 'D', '*', '#', 'p', 'w'  };
       
    38 
       
    39 const TInt  KSignalInbandDtmf = 1;
       
    40 const TInt  KSignalOutbandDtmf = 2;
       
    41 
       
    42 const TInt  KDurationNotApplicable = 1000000000;
       
    43 
       
    44 // Pause in DTMF string sending when next digit to handle is 'p' char
       
    45 const TUint KDTMFPauseLengthInUs    = 2500000;
       
    46 const TInt  KNumOfFinalPackets      = 3;
       
    47 const TReal KUsToSecFactor          = 0.000001;
       
    48 const TReal KMsToSecFactor          = 0.001;
       
    49 const TUint KDtmfDefSampleRate      = 8000;
       
    50 const TUint KFactor1000             = 1000;
       
    51 const TInt  KDefaultTickPeriodInMs  = 1;
       
    52 
       
    53 // ======== MEMBER FUNCTIONS ========
       
    54 
       
    55 
       
    56 // ---------------------------------------------------------------------------
       
    57 // CDTMFPayloadFormatWrite::CDTMFPayloadFormatWrite
       
    58 // C++ default constructor can NOT contain any code, that
       
    59 // might leave.
       
    60 // ---------------------------------------------------------------------------
       
    61 //
       
    62 CDTMFPayloadFormatWrite::CDTMFPayloadFormatWrite()
       
    63     :
       
    64     iSampleRate( KDtmfDefSampleRate ), 
       
    65     iTickPeriod( KDefaultTickPeriodInMs )
       
    66     {
       
    67     DP_DTMF_WRITE( _L("CDTMFPayloadFormatWrite::CDTMFPayloadFormatWrite") );
       
    68     }
       
    69 
       
    70 // ---------------------------------------------------------------------------
       
    71 // CDTMFPayloadFormatWrite::ConstructL
       
    72 // Symbian 2nd phase constructor can leave.
       
    73 // ---------------------------------------------------------------------------
       
    74 //
       
    75 void CDTMFPayloadFormatWrite::ConstructL( MDataSink* aSink )
       
    76     {
       
    77     DP_DTMF_WRITE( _L("CDTMFPayloadFormatWrite::ConstructL") );
       
    78     
       
    79     iFourCC = TFourCC( KMccFourCCIdDTMF );
       
    80     
       
    81     // Set data sink
       
    82     CMccRtpDataSink* tmp = static_cast<CMccRtpDataSink*>( aSink );
       
    83     iRtpDataSink = static_cast<MMccRtpDataSink*>( tmp );
       
    84     iClip = aSink;
       
    85     
       
    86     // Allocate buffer for payload encoder
       
    87     iSinkBuffer = CMMFDataBuffer::NewL( KDTMFDefaultPayloadSize );
       
    88     iPayloadEncoder = CDTMFPayloadEncoder::NewL();
       
    89     
       
    90     // Initialize state machine
       
    91     iStateMachine = CDtmfEncStateMachine::NewL( *this );
       
    92     
       
    93     TUint validDigitCount = sizeof ( KValidDTMFDigits ) / sizeof ( TUint8 );
       
    94     for ( TUint i = 0; i < validDigitCount; i++ )
       
    95         {
       
    96         iValidDigits.Append( KValidDTMFDigits[ i ] );
       
    97         }
       
    98     
       
    99     TInt err = HAL::Get( HAL::ENanoTickPeriod, iTickPeriod );
       
   100     if ( KErrNone != err )
       
   101         {
       
   102         DP_DTMF_WRITE2( _L("CDTMFPayloadFormatWrite::ConstructL HAL ERR: %d"),
       
   103             err );
       
   104         }
       
   105     
       
   106     iTickPeriod = TInt( iTickPeriod * KMsToSecFactor );
       
   107     iSendTimer = CDtmfHighResTimer::NewL( CActive::EPriorityHigh );
       
   108     }
       
   109 
       
   110 // ---------------------------------------------------------------------------
       
   111 // CDTMFPayloadFormatWrite::NewL
       
   112 // Two-phased constructor.
       
   113 // ---------------------------------------------------------------------------
       
   114 //
       
   115 CDTMFPayloadFormatWrite* CDTMFPayloadFormatWrite::NewL( MDataSink* aSink )
       
   116     {
       
   117     DP_DTMF_WRITE( _L("CDTMFPayloadFormatWrite::NewL") );
       
   118     
       
   119     if ( !aSink ) 
       
   120         {
       
   121         User::Leave ( KErrArgument );
       
   122         }
       
   123 
       
   124     if ( KMccRtpSinkUid != aSink->DataSinkType() )
       
   125         {
       
   126         User::Leave ( KErrNotSupported );
       
   127         }
       
   128     
       
   129     CDTMFPayloadFormatWrite* self = new( ELeave ) CDTMFPayloadFormatWrite;
       
   130     
       
   131     CleanupStack::PushL( self );
       
   132     self->ConstructL( aSink );
       
   133     CleanupStack::Pop( self );
       
   134 
       
   135     return self;
       
   136     }
       
   137 
       
   138 // ---------------------------------------------------------------------------
       
   139 // CDTMFPayloadFormatWrite::~CDTMFPayloadFormatWrite
       
   140 // Destructor.
       
   141 // ---------------------------------------------------------------------------
       
   142 //
       
   143 CDTMFPayloadFormatWrite::~CDTMFPayloadFormatWrite()
       
   144     {
       
   145     DP_DTMF_WRITE( _L("CDTMFPayloadFormatWrite::~CDTMFPayloadFormatWrite") );
       
   146     
       
   147     delete iSinkBuffer;
       
   148     delete iPayloadEncoder;
       
   149     delete iSendTimer;
       
   150     delete iStateMachine;
       
   151     iEventHandler = NULL;
       
   152     iRtpDataSink = NULL;
       
   153     
       
   154     // Media clock is not owned
       
   155     if ( iRtpMediaClock )
       
   156         {
       
   157         iRtpMediaClock->UnregisterMediaFormat( iKey );
       
   158         iRtpMediaClock = NULL;
       
   159         }
       
   160     
       
   161     iSendBuffer.Close();
       
   162     iValidDigits.Close();
       
   163     }
       
   164 
       
   165 // ---------------------------------------------------------------------------
       
   166 // CDTMFPayloadFormatWrite::HandleTimerEventL
       
   167 // STATIC METHOD. Passes timer events to the class instance interested
       
   168 // about them.
       
   169 // ---------------------------------------------------------------------------
       
   170 //
       
   171 TInt CDTMFPayloadFormatWrite::HandleTimerEventL( TAny* aObjectPtr )
       
   172     {
       
   173     if ( aObjectPtr )
       
   174         {
       
   175         return static_cast<CDTMFPayloadFormatWrite*>( aObjectPtr )->
       
   176                                                         DoHandleTimerEventL();
       
   177         }
       
   178     else
       
   179         {
       
   180         return KErrArgument;
       
   181         }
       
   182     }
       
   183     
       
   184 // ---------------------------------------------------------------------------
       
   185 // CDTMFPayloadFormatWrite::SinkThreadLogon
       
   186 // Passes the logon command to the sink clip.
       
   187 // ---------------------------------------------------------------------------
       
   188 //
       
   189 TInt CDTMFPayloadFormatWrite::SinkThreadLogon( 
       
   190     MAsyncEventHandler& aEventHandler )
       
   191     {
       
   192     DP_DTMF_WRITE( _L("CDTMFPayloadFormatWrite::SinkThreadLogon") );
       
   193     
       
   194     iEventHandler = &aEventHandler;
       
   195     return iClip->SinkThreadLogon( aEventHandler );
       
   196     }
       
   197 
       
   198 // ---------------------------------------------------------------------------
       
   199 // CDTMFPayloadFormatWrite::SinkThreadLogoff
       
   200 // Passes the logoff command to the sink clip.
       
   201 // ---------------------------------------------------------------------------
       
   202 //
       
   203 void CDTMFPayloadFormatWrite::SinkThreadLogoff()
       
   204     {
       
   205     DP_DTMF_WRITE( _L("CDTMFPayloadFormatWrite::SinkThreadLogoff") );
       
   206     
       
   207     iClip->SinkThreadLogoff();
       
   208     }
       
   209 
       
   210 // ---------------------------------------------------------------------------
       
   211 // CDTMFPayloadFormatWrite::CanCreateSinkBuffer
       
   212 // EmptyBufferL() is not used.
       
   213 // ---------------------------------------------------------------------------
       
   214 //
       
   215 TBool CDTMFPayloadFormatWrite::CanCreateSinkBuffer()
       
   216     {
       
   217     return EFalse;
       
   218     }
       
   219     
       
   220 // ---------------------------------------------------------------------------
       
   221 // CDTMFPayloadFormatWrite::CreateSinkBufferL
       
   222 // Create a sink buffer.
       
   223 // ---------------------------------------------------------------------------
       
   224 //
       
   225 CMMFBuffer* CDTMFPayloadFormatWrite::CreateSinkBufferL( 
       
   226     TMediaId /*aMediaId*/,
       
   227     TBool& /*aReference*/ )
       
   228     {
       
   229     DP_DTMF_WRITE( _L("CDTMFPayloadFormatWrite::CreateSinkBufferL") );
       
   230     
       
   231     User::Leave( KErrNotSupported );
       
   232     // PC_LINT #527, for compiler warning
       
   233     return NULL;
       
   234     }
       
   235 
       
   236 // ---------------------------------------------------------------------------
       
   237 // CDTMFPayloadFormatWrite::SetSinkDataTypeCode
       
   238 // Set the sink data type to the given FourCC code for the given media.
       
   239 // ---------------------------------------------------------------------------
       
   240 //
       
   241 TInt CDTMFPayloadFormatWrite::SetSinkDataTypeCode( TFourCC aSinkFourCC, 
       
   242                                                    TMediaId aMediaId )
       
   243     {
       
   244     DP_DTMF_WRITE( _L("CDTMFPayloadFormatWrite::SetSinkDataTypeCode") );
       
   245 
       
   246     if ( KUidMediaTypeAudio != aMediaId.iMediaType )
       
   247         {
       
   248         return KErrNotSupported;
       
   249         }
       
   250     
       
   251     iFourCC = aSinkFourCC;
       
   252     return KErrNone;
       
   253     }
       
   254 
       
   255 // ---------------------------------------------------------------------------
       
   256 // CDTMFPayloadFormatWrite::SinkDataTypeCode
       
   257 // Return the sink data type (four CC code) for the given media.
       
   258 // ---------------------------------------------------------------------------
       
   259 //
       
   260 TFourCC CDTMFPayloadFormatWrite::SinkDataTypeCode( TMediaId aMediaId )
       
   261     {
       
   262     DP_DTMF_WRITE( _L("CDTMFPayloadFormatWrite::SinkDataTypeCode") );
       
   263     
       
   264     if ( KUidMediaTypeAudio == aMediaId.iMediaType )
       
   265         {
       
   266         return iFourCC;
       
   267         }
       
   268     else
       
   269         {
       
   270         // Defaults to 'NULL' fourCC
       
   271         return TFourCC();
       
   272         }
       
   273     }
       
   274 
       
   275 // ---------------------------------------------------------------------------
       
   276 // CDTMFPayloadFormatWrite::FrameTimeInterval
       
   277 // Gets audio frame size in milliseconds.
       
   278 // ---------------------------------------------------------------------------
       
   279 //
       
   280 TTimeIntervalMicroSeconds CDTMFPayloadFormatWrite::FrameTimeInterval( 
       
   281     TMediaId aMediaType ) const
       
   282     {
       
   283     DP_DTMF_WRITE( _L("CDTMFPayloadFormatWrite::FrameTimeInterval") );
       
   284     
       
   285     if ( KUidMediaTypeAudio == aMediaType.iMediaType )
       
   286         {
       
   287         return TTimeIntervalMicroSeconds( TInt64( 0 ) );
       
   288         }
       
   289     else
       
   290         {
       
   291         return TTimeIntervalMicroSeconds( TInt64( 0 ) );
       
   292         }
       
   293     }
       
   294 
       
   295 // ---------------------------------------------------------------------------
       
   296 // CDTMFPayloadFormatWrite::Duration
       
   297 // Gets the duration of the sink clip for the specified media ID.
       
   298 // ---------------------------------------------------------------------------
       
   299 //
       
   300 TTimeIntervalMicroSeconds CDTMFPayloadFormatWrite::Duration( 
       
   301     TMediaId /*aMediaType*/ ) const
       
   302     {
       
   303     DP_DTMF_WRITE( _L("CDTMFPayloadFormatWrite::Duration") );
       
   304     
       
   305     return TTimeIntervalMicroSeconds( TInt64( KDurationNotApplicable ) );
       
   306     }
       
   307 
       
   308 // ---------------------------------------------------------------------------
       
   309 // CDTMFPayloadFormatWrite::BufferEmptiedL
       
   310 // Called by RTP data sink. Indicates that DTMF data is sent to the network.
       
   311 // ---------------------------------------------------------------------------
       
   312 //
       
   313 void CDTMFPayloadFormatWrite::BufferEmptiedL( CMMFBuffer* /*aBuffer*/ )
       
   314     {
       
   315     DP_DTMF_WRITE( _L("CDTMFPayloadFormatWrite::BufferEmptiedL") );
       
   316     
       
   317     // Nothing to do
       
   318     }
       
   319     
       
   320 // ---------------------------------------------------------------------------
       
   321 // CDTMFPayloadFormatWrite::SinkPrimeL
       
   322 // Passes prime transition to the RTP data sink.
       
   323 // ---------------------------------------------------------------------------
       
   324 //
       
   325 void CDTMFPayloadFormatWrite::SinkPrimeL()
       
   326     {
       
   327     DP_DTMF_WRITE( _L("CDTMFPayloadFormatWrite::SinkPrimeL") );
       
   328     
       
   329     iClip->SinkPrimeL();
       
   330     
       
   331     // If the possible state machine in clip does not leave, let dtmf payload
       
   332     // formatter also allow re-priming from any state.
       
   333     CancelDTMFStringSending();
       
   334     }
       
   335 
       
   336 // ---------------------------------------------------------------------------
       
   337 // CDTMFPayloadFormatWrite::SinkPlayL
       
   338 // Passes play transition to the RTP data sink and resets state variables.
       
   339 // ---------------------------------------------------------------------------
       
   340 //
       
   341 void CDTMFPayloadFormatWrite::SinkPlayL()
       
   342     {
       
   343     DP_DTMF_WRITE( _L("CDTMFPayloadFormatWrite::SinkPlayL") );
       
   344     
       
   345     iClip->SinkPlayL();
       
   346     }
       
   347     
       
   348 // ---------------------------------------------------------------------------
       
   349 // CDTMFPayloadFormatWrite::SinkPauseL
       
   350 // Passes pause transition to the RTP data sink.
       
   351 // ---------------------------------------------------------------------------
       
   352 //
       
   353 void CDTMFPayloadFormatWrite::SinkPauseL()
       
   354     {
       
   355     DP_DTMF_WRITE( _L("CDTMFPayloadFormatWrite::SinkPauseL") );
       
   356     
       
   357     CancelDTMFStringSending();
       
   358     iClip->SinkPauseL();
       
   359     }
       
   360 
       
   361 // ---------------------------------------------------------------------------
       
   362 // CDTMFPayloadFormatWrite::SinkStopL
       
   363 // Passes stop transition to the RTP data sink.
       
   364 // ---------------------------------------------------------------------------
       
   365 //  
       
   366 void CDTMFPayloadFormatWrite::SinkStopL()
       
   367     {
       
   368     DP_DTMF_WRITE( _L("CDTMFPayloadFormatWrite::SinkStopL") );
       
   369     
       
   370     CancelDTMFStringSending();
       
   371     iClip->SinkStopL();
       
   372     }
       
   373 
       
   374 // ---------------------------------------------------------------------------
       
   375 // CDTMFPayloadFormatWrite::EmptyBufferL
       
   376 // Not used because DTMF payload formatter generates DTMF independently.
       
   377 // ---------------------------------------------------------------------------
       
   378 //
       
   379 void CDTMFPayloadFormatWrite::EmptyBufferL( CMMFBuffer* /*aBuffer*/, 
       
   380                                             MDataSource* /*aSupplier*/, 
       
   381                                             TMediaId /*aMediaId*/ )
       
   382     {
       
   383     DP_DTMF_WRITE( _L("CDTMFPayloadFormatWrite::EmptyBufferL") );
       
   384     
       
   385     User::Leave( KErrNotSupported );
       
   386     }
       
   387                     
       
   388 // ---------------------------------------------------------------------------
       
   389 // CDTMFPayloadFormatWrite::PayloadFormat
       
   390 // Returns payload format used in DTMF encoding.
       
   391 // ---------------------------------------------------------------------------
       
   392 //
       
   393 TDTMFPayloadFormat CDTMFPayloadFormatWrite::PayloadFormat() const
       
   394     {
       
   395     DP_DTMF_WRITE( _L("CDTMFPayloadFormatWrite::PayloadFormat") );
       
   396     
       
   397     return iPayloadFormat;
       
   398     }
       
   399 
       
   400 // ---------------------------------------------------------------------------
       
   401 // CDTMFPayloadFormatWrite::SetPayloadFormat
       
   402 // Sets payload format used in DTMF encoding.
       
   403 // ---------------------------------------------------------------------------
       
   404 //
       
   405 TInt CDTMFPayloadFormatWrite::SetPayloadFormat( 
       
   406     TDTMFPayloadFormat aPayloadFormat )
       
   407     {
       
   408     DP_DTMF_WRITE2( _L("CDTMFPayloadFormatWrite::SetPayloadFormat - Format: %d"), aPayloadFormat );
       
   409     
       
   410     TInt err = iPayloadEncoder->SetPayloadFormat( aPayloadFormat );
       
   411     if ( KErrNone == err )
       
   412         {
       
   413         iPayloadFormat = aPayloadFormat;
       
   414         }
       
   415 
       
   416     return err;
       
   417     }
       
   418             
       
   419 // ---------------------------------------------------------------------------
       
   420 // CDTMFPayloadFormatWrite::StartDTMFToneL
       
   421 // Starts a timer which sends specified DTMF digit periodically until 
       
   422 // StopDTMFTone() is called.
       
   423 // ---------------------------------------------------------------------------
       
   424 //
       
   425 void CDTMFPayloadFormatWrite::StartDTMFToneL( const TChar aTone )
       
   426     {
       
   427     TUint32 tickCount( User::NTickCount() );
       
   428     
       
   429     DP_DTMF_WRITE3(  _L("CDTMFPayloadFormatWrite::StartDTMFToneL aTone = %c, tick = %u"),
       
   430         static_cast<TUint>( aTone ), tickCount );
       
   431     
       
   432     DP_DTMF_WRITE2( _L("CDTMFPayloadFormatWrite::StartDTMFToneL enc state %d"),
       
   433         iStateMachine->State() );
       
   434     
       
   435     __ASSERT_ALWAYS( IsValidDigit( aTone ), User::Leave( KErrArgument ) );
       
   436     
       
   437     iSendingMode = EModeManual;
       
   438     
       
   439     TSendBufferElement element( aTone, tickCount );
       
   440     iSendBuffer.AppendL( element );
       
   441     
       
   442     if ( EStateSendingIdle == iStateMachine->State() )
       
   443         {
       
   444         if ( KSignalOutbandDtmf == iGenerationMode )
       
   445             {
       
   446             iSinkBuffer->Data().FillZ( KDTMFDefaultPayloadSize );
       
   447             }
       
   448 
       
   449         iStateMachine->ChangeStateTo( EStateEncodeNextDigit );
       
   450         }
       
   451     else
       
   452         {
       
   453         DP_DTMF_WRITE( 
       
   454             _L("CDTMFPayloadFormatWrite::StartDTMFToneL - REQ BUFFERED") );
       
   455         }
       
   456     }
       
   457 
       
   458 // ---------------------------------------------------------------------------
       
   459 // CDTMFPayloadFormatWrite::StopDTMFToneL
       
   460 // Stops the timer for DTMF digit update packet sending. Starts a timer for 
       
   461 // sending Final Packet three times according to RFC 2833, section 2.5.1.4.
       
   462 // ---------------------------------------------------------------------------
       
   463 //
       
   464 void CDTMFPayloadFormatWrite::StopDTMFToneL()
       
   465     {
       
   466     TUint32 tickCount( User::NTickCount() );
       
   467     DP_DTMF_WRITE2( _L("CDTMFPayloadFormatWrite::StopDTMFTone, tick = %u"),
       
   468         tickCount );
       
   469     
       
   470     // set stop time to the first unupdated element
       
   471     TBool elementFound( EFalse );
       
   472     TInt index( 0 );
       
   473     while ( !elementFound && index < iSendBuffer.Count() )
       
   474         {
       
   475         if ( iSendBuffer[index].StopTime() == 0 )
       
   476             {
       
   477             iSendBuffer[index].SetStopTime( tickCount );
       
   478             if ( iSendBuffer[index].StopTime() == 0 )
       
   479                 {
       
   480                 // mark stop time as updated to prevent update of the same 
       
   481                 // element in future
       
   482                 iSendBuffer[index].SetStopTime( 1 );
       
   483                 }
       
   484             
       
   485             elementFound = ETrue;
       
   486             }
       
   487         
       
   488         index++;
       
   489         }
       
   490     
       
   491     if ( EStateToneOn == iStateMachine->State() )
       
   492         {
       
   493         if ( KSignalOutbandDtmf == iGenerationMode )
       
   494             {
       
   495             if ( EDTMFPayloadFormatEvent == iPayloadFormat
       
   496                 || EDTMFPayloadFormatRedEvents == iPayloadFormat )
       
   497                 {
       
   498                 // Send final packet with "E" bit set. According to 
       
   499                 // RFC 2833 2.5.1.4 final packet SHOULD be sent three times.
       
   500                 iPayloadEncoder
       
   501                     ->UpdateEventPayload( ETrue, iToneDuration, iSinkBuffer );
       
   502                 iStateMachine->ChangeStateTo( EStateToneOff );
       
   503                 }
       
   504             else if ( EDTMFPayloadFormatTone == iPayloadFormat )
       
   505                 {
       
   506                 // Tone Payload Format doesn't have final packet redundancy
       
   507                 iPayloadEncoder->UpdateTonePayload( iToneDuration, 
       
   508                                                                 iSinkBuffer );
       
   509                 }
       
   510             else
       
   511                 {
       
   512                 // Not acceptable payload format
       
   513                 }
       
   514             }
       
   515         else
       
   516             {
       
   517             iStateMachine->ChangeStateTo( EStateToneOff );
       
   518             }
       
   519         }
       
   520     else
       
   521         {
       
   522         DP_DTMF_WRITE( _L("CDTMFPayloadFormatWrite::StopDTMFTone OUT-OF-SYNC") );
       
   523         }
       
   524     }
       
   525 
       
   526 // ---------------------------------------------------------------------------
       
   527 // CDTMFPayloadFormatWrite::SendDTMFTonesL
       
   528 // Starts to send DTMF string incrementally until the string is sent.
       
   529 // ---------------------------------------------------------------------------
       
   530 //
       
   531 void CDTMFPayloadFormatWrite::SendDTMFTonesL( const TDesC8& aTones )
       
   532     {
       
   533     DP_DTMF_WRITE( _L("CDTMFPayloadFormatWrite::SendDTMFTonesL") );
       
   534     
       
   535     TInt digitCount( aTones.Length() );
       
   536     __ASSERT_ALWAYS( digitCount != 0, User::Leave( KErrArgument ) );
       
   537     __ASSERT_ALWAYS( IsValidDigits( aTones ), User::Leave( KErrArgument ) );
       
   538     __ASSERT_ALWAYS( !iSendTimer->IsActive(), User::Leave( KErrNotReady ) );
       
   539     
       
   540     iSendingMode = EModeAutomatic;
       
   541     
       
   542     iSendBuffer.Reset();
       
   543     for ( TInt i = 0; i < digitCount; i++ )
       
   544         {
       
   545         // in automatic mode default durations for tones are used
       
   546         TSendBufferElement element( aTones[i], 0 );
       
   547         iSendBuffer.AppendL( element );
       
   548         }
       
   549     
       
   550     iSinkBuffer->Data().FillZ( KDTMFDefaultPayloadSize );
       
   551     iStateMachine->ChangeStateTo( EStateEncodeNextDigit );
       
   552     }
       
   553 
       
   554 // ---------------------------------------------------------------------------
       
   555 // CDTMFPayloadFormatWrite::NotifyStopInDTMFString
       
   556 // Request to notify client when stop in DTMF string is
       
   557 // encountered ('w' char).
       
   558 // ---------------------------------------------------------------------------
       
   559 //    
       
   560 void CDTMFPayloadFormatWrite::NotifyStopInDTMFString( TBool aFlag )
       
   561     {
       
   562     DP_DTMF_WRITE2( _L("CDTMFPayloadFormatWrite::NotifyStopInDTMFString - Flag: %d"), aFlag );
       
   563     
       
   564     iNotifyStopReq = aFlag;
       
   565     }
       
   566 
       
   567 // ---------------------------------------------------------------------------
       
   568 // CDTMFPayloadFormatWrite::ContinueDTMFStringSending
       
   569 // Allows a client to continue or cancel the sending of a DTMF string when it 
       
   570 // was stopped by the use of 'w' char in the string.
       
   571 // ---------------------------------------------------------------------------
       
   572 //
       
   573 TInt CDTMFPayloadFormatWrite::ContinueDTMFStringSending( TBool aContinue )
       
   574     {
       
   575     DP_DTMF_WRITE2( _L("CDTMFPayloadFormatWrite::ContinueDTMFStringSending - aContinue: %d"), aContinue );
       
   576     
       
   577     if ( aContinue )
       
   578         {
       
   579         // Start continue send rest digits incrementally
       
   580         iStateMachine->ChangeStateTo( EStateEncodeNextDigit );
       
   581         }
       
   582     else
       
   583         {
       
   584         iSendBuffer.Reset();
       
   585         iStateMachine->ChangeStateTo( EStateSendingIdle );
       
   586         }
       
   587     
       
   588     return KErrNone;
       
   589     }
       
   590 
       
   591 // ---------------------------------------------------------------------------
       
   592 // CDTMFPayloadFormatWrite::CancelDTMFStringSending
       
   593 // 
       
   594 // ---------------------------------------------------------------------------
       
   595 //    
       
   596 void CDTMFPayloadFormatWrite::CancelDTMFStringSending()
       
   597     {
       
   598     DP_DTMF_WRITE( _L("CDTMFPayloadFormatWrite::CancelDTMFStringSending") );
       
   599     
       
   600     iSendBuffer.Reset();
       
   601     iSendTimer->Cancel();
       
   602     iStateMachine->ResetStateMachine();
       
   603     }
       
   604            
       
   605 // ---------------------------------------------------------------------------
       
   606 // CDTMFPayloadFormatWrite::DeliverPacketL
       
   607 // Prepare the RTP packet header and deliver the packet to the datasink.
       
   608 // ---------------------------------------------------------------------------
       
   609 //
       
   610 void CDTMFPayloadFormatWrite::DeliverPacketL( CMMFDataBuffer& aPayload, 
       
   611                                               TBool aMarkerBit )
       
   612     {
       
   613     DP_DTMF_WRITE4( 
       
   614         _L("CDTMFPayloadFormatWrite::DeliverPacketL - TSTAMP: %u, TDUR: %d, tick = %u"),
       
   615         TUint32( aPayload.TimeToPlay().Int64() ), iToneDuration, 
       
   616         User::NTickCount() );
       
   617     
       
   618     if ( KSignalOutbandDtmf == iGenerationMode )
       
   619         {
       
   620         // Set the marker bit if it is very first packet.
       
   621         if ( aMarkerBit )
       
   622             {
       
   623             iRtpSendHeader.iMarker = 1;
       
   624             }
       
   625         else
       
   626             {
       
   627             iRtpSendHeader.iMarker = 0;
       
   628             }
       
   629             
       
   630         // Construct RTP header.
       
   631         if ( EGenRedUsed == iCInfo.iAlgoUsed )
       
   632             {
       
   633             iRtpSendHeader.iPayloadType = iCInfo.iRedundantPayload;
       
   634             }
       
   635         else
       
   636             {
       
   637             iRtpSendHeader.iPayloadType = iCInfo.iPayloadType;
       
   638             }
       
   639 
       
   640         // Timestamp must be updated before coming here
       
   641         iRtpSendHeader.iTimestamp = TUint32( aPayload.TimeToPlay().Int64() );
       
   642 
       
   643         // Deliver the packet
       
   644         iRtpDataSink->EmptyBufferL( &aPayload, this,
       
   645             TMediaId( KUidMediaTypeAudio ), iRtpSendHeader );
       
   646 
       
   647         // Do not reset payload buffer because update packets
       
   648         // are send based on same buffer.
       
   649         }
       
   650     else
       
   651         {
       
   652         DP_DTMF_WRITE( _L("CDTMFPayloadFormatWrite::DeliverPacketL - INBAND TONE") );
       
   653         }
       
   654     }
       
   655 
       
   656 // ---------------------------------------------------------------------------
       
   657 // CDTMFPayloadFormatWrite::IsValidDigit
       
   658 // Check is digit valid DTMF.
       
   659 // ---------------------------------------------------------------------------
       
   660 //
       
   661 TBool CDTMFPayloadFormatWrite::IsValidDigits( 
       
   662         const TDesC8& aDigits ) const
       
   663     {
       
   664     TBool isValid( ETrue );
       
   665     TInt index( aDigits.Length() - 1 );
       
   666     while ( isValid && 0 <= index )
       
   667         {
       
   668         if ( KErrNotFound == iValidDigits.Find( aDigits[ index ] ) )
       
   669             {
       
   670             isValid = EFalse;
       
   671             }
       
   672         
       
   673         index--;
       
   674         }
       
   675     
       
   676     return isValid;
       
   677     }
       
   678     
       
   679 // ---------------------------------------------------------------------------
       
   680 // CDTMFPayloadFormatWrite::SetSinkPrioritySettings
       
   681 // Used to tell audio policy whether to mix locally played DTMFs to the record
       
   682 // stream.
       
   683 // ---------------------------------------------------------------------------
       
   684 //
       
   685 void CDTMFPayloadFormatWrite::SetSinkPrioritySettings( 
       
   686     const TMMFPrioritySettings& /*aPrioritySettings*/ )
       
   687     {
       
   688     DP_DTMF_WRITE( _L("CDTMFPayloadFormatWrite::SetSinkPrioritySettings") );
       
   689     }
       
   690 
       
   691 // ---------------------------------------------------------------------------
       
   692 // CDTMFPayloadFormatWrite::HandleControlChar
       
   693 // Takes care of handling 'p' and 'w' chars in a DTMF string.
       
   694 // ---------------------------------------------------------------------------
       
   695 //
       
   696 void CDTMFPayloadFormatWrite::HandleControlChar( const TChar& aChar )
       
   697     {
       
   698     if ( 'p' == aChar )
       
   699         {
       
   700         // 'p' char is interpreted as a 2.5 second pause
       
   701         DP_DTMF_WRITE( _L("CDTMFPayloadFormatWrite::HandleControlChar - PAUSE DETECTED") );
       
   702         iSendTimer->Cancel();
       
   703         iStateMachine->ChangeStateTo( EStateSendPaused );
       
   704         TCallBack callBack( HandleTimerEventL, this );
       
   705         iSendTimer->Start( 
       
   706             TTimeIntervalMicroSeconds32( KDTMFPauseLengthInUs ),
       
   707             TTimeIntervalMicroSeconds32( KDTMFPauseLengthInUs ), 
       
   708             callBack );
       
   709         }
       
   710     else if ( 'w' == aChar )
       
   711         {
       
   712         // Stop in a DTMF string
       
   713         DP_DTMF_WRITE( _L("CDTMFPayloadFormatWrite::HandleControlChar - STOP DETECTED ") );
       
   714 
       
   715         if ( iNotifyStopReq )
       
   716             {
       
   717             iSendTimer->Cancel();
       
   718             iStateMachine->ChangeStateTo( EStateSendStopped );
       
   719 
       
   720             SendEventSignalToClient( KMccDtmfStopInDtmfString );
       
   721             }
       
   722         }
       
   723     else
       
   724         {
       
   725         // not a control character
       
   726         }
       
   727     }
       
   728 
       
   729 // ---------------------------------------------------------------------------
       
   730 // CDTMFPayloadFormatWrite::ConfigurePayloadFormatL
       
   731 // Configure payload encoding parameters.
       
   732 // ---------------------------------------------------------------------------
       
   733 //
       
   734 void CDTMFPayloadFormatWrite::ConfigurePayloadFormatL( 
       
   735     const TDesC8& aConfigParams,
       
   736     CMccRtpMediaClock& aClock )
       
   737     {
       
   738     DP_DTMF_WRITE( _L("CDTMFPayloadFormatWrite::ConfigurePayloadFormatL IN") );
       
   739     
       
   740     __ASSERT_ALWAYS( aConfigParams.Size() == sizeof( TMccCodecInfo ),
       
   741         User::Leave( KErrArgument ) );
       
   742     
       
   743     TMccCodecInfoBuffer infoBuffer;
       
   744     infoBuffer.Copy( aConfigParams );
       
   745     iCInfo = infoBuffer();
       
   746     
       
   747     if ( !iPayloadEncoder )
       
   748         {
       
   749         iPayloadEncoder = CDTMFPayloadEncoder::NewL();
       
   750         }
       
   751     
       
   752     iPayloadEncoder->SetPayloadType( iCInfo.iPayloadType );
       
   753     
       
   754     // Redundancy configuration, always using generic redundacy.
       
   755     if ( iCInfo.iRedundancyCount && KMaxDtmfRedCount >=
       
   756          iCInfo.iRedundancyCount )
       
   757         {
       
   758         DP_DTMF_WRITE2( _L("CDTMFPayloadFormatWrite::ConfigurePayloadFormatL iAlgoUsed: %d"),
       
   759             iCInfo.iAlgoUsed );
       
   760         
       
   761         __ASSERT_ALWAYS( EGenRedUsed == iCInfo.iAlgoUsed,
       
   762             User::Leave( KErrArgument ) );
       
   763             
       
   764         User::LeaveIfError(
       
   765             iPayloadEncoder->SetPayloadFormat( EDTMFPayloadFormatRedEvents ) );
       
   766         }
       
   767     else
       
   768         {
       
   769         // Make sure that the EGenRedUsed is not set
       
   770         iCInfo.iAlgoUsed = ENoAlgoUsed;
       
   771         }
       
   772     
       
   773     // Inband/Outband configuration
       
   774     if ( EDTMFModeInband == iCInfo.iCodecMode )
       
   775         {
       
   776         iGenerationMode = KSignalInbandDtmf;
       
   777         }
       
   778     else
       
   779         {
       
   780         iGenerationMode = KSignalOutbandDtmf;
       
   781         
       
   782         // Check if we need to unreg from current media clock.
       
   783         if ( iRtpMediaClock )
       
   784             {
       
   785             iRtpMediaClock->UnregisterMediaFormat( iKey );
       
   786             }
       
   787         
       
   788         iKey = aClock.RegisterMediaFormat( iSampleRate, iCInfo.iPtime );
       
   789         }
       
   790     
       
   791     iRtpMediaClock = &aClock;
       
   792     
       
   793     DP_DTMF_WRITE( _L("CDTMFPayloadFormatWrite::ConfigurePayloadFormatL OUT") );
       
   794     }
       
   795 
       
   796 // ---------------------------------------------------------------------------
       
   797 // CDTMFPayloadFormatWrite::DoHandleTimerEvent
       
   798 // Does actions depending on current state on timer event.
       
   799 // ---------------------------------------------------------------------------
       
   800 //
       
   801 TInt CDTMFPayloadFormatWrite::DoHandleTimerEventL()
       
   802     {
       
   803     switch ( iStateMachine->State() )
       
   804         {
       
   805         case EStateToneOn:
       
   806             this->DoToneOnActionsL( EFalse );
       
   807             break;
       
   808         
       
   809         case EStateToneOff:
       
   810             this->DoToneOffActionsL( EFalse );
       
   811             break;
       
   812         
       
   813         case EStateSendPaused:
       
   814             iSendTimer->Cancel();
       
   815             iStateMachine->ChangeStateTo( EStateEncodeNextDigit );
       
   816             break;
       
   817         
       
   818         default:
       
   819             DP_DTMF_WRITE(_L("CDTMFPayloadFormatWrite::DoHandleTimerEvent DEFAULT") );
       
   820             break;
       
   821         }
       
   822     
       
   823     return ETrue;
       
   824     }
       
   825 
       
   826 // ---------------------------------------------------------------------------
       
   827 // CDTMFPayloadFormatWrite::EncodeNextDigitL
       
   828 // Encodes next digit in sequence.
       
   829 // ---------------------------------------------------------------------------
       
   830 //
       
   831 void CDTMFPayloadFormatWrite::EncodeNextDigitL()
       
   832     {
       
   833     DP_DTMF_WRITE2( _L("CDTMFPayloadFormatWrite::EncodeNextDigitL, tick = %u"),
       
   834         User::NTickCount() );
       
   835 
       
   836     iToneDuration = 0;
       
   837     iToneDuration += static_cast<TUint16>
       
   838         ( iCInfo.iPtime * iSampleRate * KMsToSecFactor );
       
   839     
       
   840     if ( iSendBuffer.Count() && ('p' == iSendBuffer[0].Tone() || 'w' == 
       
   841         iSendBuffer[0].Tone() ) )
       
   842         {
       
   843         HandleControlChar( iSendBuffer[0].Tone() );
       
   844         iSendBuffer.Remove( 0 );
       
   845         }
       
   846     else if ( iSendBuffer.Count() )
       
   847         {
       
   848         if ( EDTMFPayloadFormatEvent == iPayloadFormat ||
       
   849              EDTMFPayloadFormatRedEvents == iPayloadFormat )
       
   850             {
       
   851             // Encode digit to RTP packet using Payload Format
       
   852             // for Named Events
       
   853             TDTMFEventPayloadInfo eventInfo;
       
   854             eventInfo.SetEvent( iSendBuffer[0].Tone() );
       
   855             eventInfo.SetVolume( KDTMFDefaultToneVolume );
       
   856             eventInfo.SetDuration( iToneDuration );
       
   857             
       
   858             if ( KSignalOutbandDtmf == iGenerationMode )
       
   859                 {
       
   860                 TUint32 timeStamp( 0 );
       
   861                 User::LeaveIfError( 
       
   862                     iRtpMediaClock->GetTimeStamp( iKey, timeStamp ) );
       
   863                 iSinkBuffer->SetTimeToPlay( 
       
   864                     TTimeIntervalMicroSeconds( TInt64( timeStamp ) ) );
       
   865                 }
       
   866             
       
   867             iPayloadEncoder->EncodeEvent( eventInfo, iSinkBuffer );
       
   868             }
       
   869         else if ( EDTMFPayloadFormatTone == iPayloadFormat )
       
   870             {
       
   871             TDTMFTonePayloadInfo toneInfo;
       
   872             toneInfo.SetModulation( KDTMFDefaultModulation );
       
   873             toneInfo.SetVolume( KDTMFDefaultToneVolume );
       
   874             toneInfo.SetDuration( iToneDuration );
       
   875             iPayloadEncoder->EncodeTone( toneInfo, iSinkBuffer );
       
   876             }
       
   877         else
       
   878             {
       
   879             // Not acceptable payload format
       
   880             DP_DTMF_WRITE2( _L("PayloadFormat not Acceptable!: %d"), 
       
   881                 iPayloadFormat );
       
   882             }
       
   883         
       
   884         iStateMachine->ChangeStateTo( EStateToneOn );
       
   885         }
       
   886     else
       
   887         {
       
   888         if ( EModeAutomatic == iSendingMode )
       
   889             {
       
   890             SendEventSignalToClient( KMccDtmfSendingComplete );
       
   891             }
       
   892 
       
   893         iStateMachine->ChangeStateTo( EStateSendingIdle );
       
   894         }
       
   895     }
       
   896     
       
   897 // ---------------------------------------------------------------------------
       
   898 // CDTMFPayloadFormatWrite::DoToneOnActionsL
       
   899 // Called by sendtimer. Does actions belonging to tone on state and exits
       
   900 // state when exit conditions are met. Actions to do are: Send update packets
       
   901 // at certain time interval.
       
   902 // ---------------------------------------------------------------------------
       
   903 //
       
   904 void CDTMFPayloadFormatWrite::DoToneOnActionsL( TBool aEntryToState )
       
   905     {
       
   906     DP_DTMF_WRITE2( _L("CDTMFPayloadFormatWrite::DoToneOnActionsL, tick = %u"),
       
   907         User::NTickCount() );
       
   908     
       
   909     if ( aEntryToState )
       
   910         {
       
   911         iSendTimer->Cancel();
       
   912         
       
   913         if ( EModeManual == iSendingMode )
       
   914             {
       
   915             SendEventSignalToClient( KMccDtmfManualStart );
       
   916             }
       
   917         else
       
   918             {
       
   919             SendEventSignalToClient( KMccDtmfSequenceStart );
       
   920             }
       
   921         
       
   922         DeliverPacketL( *iSinkBuffer, ETrue );
       
   923         
       
   924         TCallBack callBack( HandleTimerEventL, this );
       
   925         iSendTimer->Start(
       
   926             TTimeIntervalMicroSeconds32( iCInfo.iPtime * KFactor1000 ),
       
   927             TTimeIntervalMicroSeconds32( iCInfo.iPtime * KFactor1000 ),
       
   928             callBack );
       
   929         }
       
   930     else
       
   931         {
       
   932         iToneDuration += static_cast<TUint16>
       
   933             ( iCInfo.iPtime * iSampleRate * KMsToSecFactor );
       
   934         
       
   935         if ( EModeAutomatic == iSendingMode )
       
   936             {
       
   937             TUint targetDuration = 
       
   938                 TUint( KDTMFDefToneOnLengthInUs * KUsToSecFactor * 
       
   939                 iSampleRate );
       
   940 
       
   941             if ( iToneDuration >= targetDuration )
       
   942                 {
       
   943                 // Exit condition
       
   944                 iSendTimer->Cancel();
       
   945                 iPayloadEncoder->UpdateEventPayload( ETrue, iToneDuration, 
       
   946                                                                 iSinkBuffer );
       
   947                 iStateMachine->ChangeStateTo( EStateToneOff );
       
   948                 return;
       
   949                 }
       
   950             }
       
   951         else
       
   952             {
       
   953             if ( iSendBuffer[0].StopTime() != 0 &&
       
   954                  iSendBuffer[0].Duration() * iTickPeriod 
       
   955                     * iSampleRate * KUsToSecFactor <= iToneDuration )
       
   956                 {
       
   957                 // Exit condition
       
   958                 iSendTimer->Cancel();
       
   959                 iPayloadEncoder->UpdateEventPayload( ETrue, iToneDuration, 
       
   960                                                                 iSinkBuffer );
       
   961                 iStateMachine->ChangeStateTo( EStateToneOff );
       
   962                 return;
       
   963                 }
       
   964             }
       
   965 
       
   966         if ( EDTMFPayloadFormatEvent == iPayloadFormat
       
   967             || EDTMFPayloadFormatRedEvents == iPayloadFormat )
       
   968             {
       
   969             // Check is this long duration event
       
   970        		// Disabling a PC-lint warning due to if-statement always being false,
       
   971        		// as it seems the possibility should be there if values are changed
       
   972        		/*lint -e685 */
       
   973             if ( KDTMFMaxDurationFieldValue < iToneDuration )
       
   974                 {
       
   975                 iToneDuration -= KDTMFMaxDurationFieldValue;
       
   976                 iPayloadEncoder->UpdateEventPayload( EFalse, iToneDuration, 
       
   977                                                                 iSinkBuffer );
       
   978                 DeliverPacketL( *iSinkBuffer, EFalse );
       
   979                 }
       
   980 			/*lint +e685 */                
       
   981 			
       
   982             else
       
   983                 {
       
   984                 // The update packet MUST have the same RTP timestamp value as
       
   985                 // the initial packet for the event (RFC 2833, 2.5.1.2).
       
   986                 iPayloadEncoder->UpdateEventPayload( EFalse, iToneDuration, 
       
   987                                                                 iSinkBuffer );
       
   988                 DeliverPacketL( *iSinkBuffer, EFalse );
       
   989                 }    
       
   990             }
       
   991         else if ( EDTMFPayloadFormatTone == iPayloadFormat )
       
   992             {
       
   993             iPayloadEncoder->UpdateTonePayload( iToneDuration, iSinkBuffer );
       
   994             DeliverPacketL( *iSinkBuffer, EFalse );
       
   995             }
       
   996         else
       
   997             {
       
   998             // Not acceptable payload format
       
   999             }
       
  1000         }
       
  1001     }
       
  1002 
       
  1003 // ---------------------------------------------------------------------------
       
  1004 // CDTMFPayloadFormatWrite::DoToneOffActionsL
       
  1005 // Called by sendtimer. Does actions belonging to tone off state and exits
       
  1006 // state when exit conditions are met. Actions include: sending final packets.
       
  1007 // ---------------------------------------------------------------------------
       
  1008 //
       
  1009 void CDTMFPayloadFormatWrite::DoToneOffActionsL( TBool aEntryToState )
       
  1010     {
       
  1011     DP_DTMF_WRITE2( _L("CDTMFPayloadFormatWrite::DoToneOffActionsL, tick = %u"), 
       
  1012         User::NTickCount() );
       
  1013 
       
  1014     #ifdef VOIP_TRACE_ENABLED
       
  1015         VoipTrace( "%x %x", MCC_TRACE, MCC_DTMF_PLF_WRITE_SENDFINALPKT );
       
  1016     #endif
       
  1017     
       
  1018     if ( aEntryToState )
       
  1019         {
       
  1020         iSendTimer->Cancel();
       
  1021         iFinalPacketCtr = 0;
       
  1022         
       
  1023         TCallBack callBack( HandleTimerEventL, this );
       
  1024         iSendTimer->Start(
       
  1025             TTimeIntervalMicroSeconds32( iCInfo.iPtime * KFactor1000 ),
       
  1026             TTimeIntervalMicroSeconds32( iCInfo.iPtime * KFactor1000 ),
       
  1027             callBack );
       
  1028         }
       
  1029     else
       
  1030         {
       
  1031         iFinalPacketCtr++;
       
  1032         if ( KNumOfFinalPackets >= iFinalPacketCtr )
       
  1033             {
       
  1034             DeliverPacketL( *iSinkBuffer, EFalse );
       
  1035             }
       
  1036         else
       
  1037             {
       
  1038             TUint curOffDur = iFinalPacketCtr * iCInfo.iPtime * KFactor1000;
       
  1039             if ( EModeManual == iSendingMode || 
       
  1040                  KDTMFDefToneOffLengthInUs <= curOffDur )
       
  1041                 {
       
  1042                 // Prevent audio sending during final packet retransmission by
       
  1043                 // sending completion event only when also retransmissions are
       
  1044                 // done.
       
  1045                 if ( EModeManual == iSendingMode )
       
  1046                     {
       
  1047                     SendEventSignalToClient( KMccDtmfManualStop );
       
  1048                     }
       
  1049                 else
       
  1050                     {
       
  1051                     SendEventSignalToClient( KMccDtmfSequenceStop );
       
  1052                     }
       
  1053                 
       
  1054                 iSendTimer->Cancel();
       
  1055                 iFinalPacketCtr = 0;
       
  1056                 if ( iSendBuffer.Count() > 0 )
       
  1057                 	{
       
  1058                 	iSendBuffer.Remove( 0 );	
       
  1059                 	}
       
  1060                 iStateMachine->ChangeStateTo( EStateEncodeNextDigit );
       
  1061                 }
       
  1062             }
       
  1063         }
       
  1064     }
       
  1065 
       
  1066 // ---------------------------------------------------------------------------
       
  1067 // CDTMFPayloadFormatWrite::SendEventSignalToClient
       
  1068 // Signaling about events to the client.
       
  1069 // ---------------------------------------------------------------------------
       
  1070 //
       
  1071 void CDTMFPayloadFormatWrite::SendEventSignalToClient( 
       
  1072     TMccDtmfEventType aEventType ) const
       
  1073     {
       
  1074     TMccDtmfEventData eventSignal;
       
  1075     eventSignal.iDtmfEventType = aEventType;
       
  1076     TMccDtmfEventDataPackage signalPkg( eventSignal );
       
  1077 
       
  1078     if ( iEventHandler )
       
  1079         {
       
  1080         TMccEvent event( 0,
       
  1081                          0, 
       
  1082                          0, 
       
  1083                          0, 
       
  1084                          KMccEventCategoryDtmf, 
       
  1085                          KMccDtmfControl, 
       
  1086                          KErrNone, 
       
  1087                          signalPkg );
       
  1088 
       
  1089         TMccInternalEvent internalEvent( KMccDtmfFormatterUid, 
       
  1090                                          EMccInternalEventNone,
       
  1091                                          event );
       
  1092             
       
  1093         iEventHandler->SendEventToClient( internalEvent );
       
  1094         }
       
  1095     }
       
  1096 
       
  1097 // ---------------------------------------------------------------------------
       
  1098 // CDTMFPayloadFormatWrite::IsValidDigit
       
  1099 // ---------------------------------------------------------------------------
       
  1100 //
       
  1101 TBool CDTMFPayloadFormatWrite::IsValidDigit( const TChar& aTone ) const
       
  1102     {
       
  1103     return ( KErrNotFound != iValidDigits.Find( aTone ) );
       
  1104     }
       
  1105 
       
  1106 
       
  1107 //  End of File
       
  1108