sipvoipprovider/src/svpaudioutility.cpp
branchRCL_3
changeset 22 d38647835c2e
parent 0 a4daefaec16c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sipvoipprovider/src/svpaudioutility.cpp	Wed Sep 01 12:29:57 2010 +0100
@@ -0,0 +1,656 @@
+/*
+* Copyright (c) 2006-2008 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:  Provides static utility functions for SVP
+*
+*/
+
+
+#include <mceaudiostream.h>
+#include <mcertpsource.h>
+#include <mceaudiocodec.h>
+#include <mcespeakersink.h>
+#include <mcemicsource.h>
+#include <AudioPreference.h>
+#include "svpaudioutility.h"
+#include "svplogger.h"
+#include "svpconsts.h"
+#include "svpsessionbase.h"
+#include "svpemergencysession.h"
+#include "svpholdcontext.h"
+#include "svpholdcontroller.h"
+
+// LOCAL CONSTANTS
+// Constants for VoIP uplink audio preferences, renamed for better
+// readability and to clarify between IB/OB DTMF's. 
+// See <audiopreference.h> for more information.
+// Inband signalling uplink preference (i.e inband DTMF)
+const TUint KSVPAudioPrefUplinkIbDtmf = KAudioPrefVoipAudioUplinkNonSignal;
+// Outband signalling uplink preference (i.e outband DTMF)
+const TUint KSVPAudioPrefUplinkOobDtmf = KAudioPrefVoipAudioUplink;
+
+
+// ---------------------------------------------------------------------------
+// SVPAudioUtility::IsDownlinkStream
+// ---------------------------------------------------------------------------
+//
+TBool SVPAudioUtility::IsDownlinkStream( CMceAudioStream& aStream )
+    {
+    SVPDEBUG2( "SVPAudioUtility::IsDownlinkStream source: 0x%x", aStream.Source() );
+    
+    if ( aStream.Source() && KMceRTPSource == aStream.Source()->Type() )
+        {
+        SVPDEBUG1( "SVPAudioUtility::IsDownlinkStream RTP SOURCE => DOWNLINK" );
+        return ETrue;
+        }
+    else
+        {
+        SVPDEBUG1( "SVPAudioUtility::IsDownlinkStream EFalse" );
+        
+        return EFalse;
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// SVPAudioUtility::SetPriorityCodecValuesL
+// ---------------------------------------------------------------------------
+//
+TBool SVPAudioUtility::SetPriorityCodecValuesL(
+    CMceAudioStream& aAudioInStream,
+    CMceAudioStream& aAudioOutStream )
+    {
+    SVPDEBUG1("SVPAudioUtility::SetPriorityCodecValuesL In");
+    
+    // set MMF codec priorities  for all codecs in both streams
+    const TInt inCodecCount = aAudioInStream.Codecs().Count();
+    SVPDEBUG2(
+        "SVPAudioUtility::SetPriorityCodecValuesL codeccount IN: %d",
+            inCodecCount )
+     
+    const TInt outCodecCount = aAudioOutStream.Codecs().Count();
+    SVPDEBUG2(
+        "SVPAudioUtility::SetPriorityCodecValuesL codeccount OUT: %d",
+            outCodecCount )
+    
+    const TBool inDtmf = SVPAudioUtility::SetDtmfPriorityL( aAudioInStream );
+    const TBool outDtmf = SVPAudioUtility::SetDtmfPriorityL( aAudioOutStream );
+    
+    // inDtmf and outDtmf _must_ match. Either inband (both EFalse) or outband
+    // (both ETrue).
+    if ( inDtmf != outDtmf )
+        {
+        SVPDEBUG1("SVPAudioUtility::SetPriorityCodecValuesL KErrNotFound");
+        User::Leave( KErrNotFound );
+        }
+    
+    SVPDEBUG1( "SVPAudioUtility::SetPriorityCodecValuesL set IN priorities" );
+    
+    SetAudioCodecPrioritiesL( aAudioInStream, KAudioPrefVoipAudioDownlink );
+    
+    // Check which version of DTMF's are we using, inband or outband.
+    TBool outband( EFalse );
+    TUint uplinkPreference = KSVPAudioPrefUplinkIbDtmf;
+    if ( inDtmf && outDtmf )
+        {
+        SVPDEBUG1(
+            "SVPAudioUtility::SetPriorityCodecValuesL change to OOB DTMF" );
+        
+        uplinkPreference = KSVPAudioPrefUplinkOobDtmf;
+        outband = ETrue;
+        }
+    // else inband used.
+    
+    SVPDEBUG1( "SVPAudioUtility::SetPriorityCodecValuesL set OUT priorities" );
+    
+    SetAudioCodecPrioritiesL( aAudioOutStream, uplinkPreference );
+    
+    SVPDEBUG1( "SVPAudioUtility::SetPriorityCodecValuesL Out" );
+    
+    return outband;
+    }
+
+// ---------------------------------------------------------------------------
+// SVPAudioUtility::SetDtmfPriorityL
+// ---------------------------------------------------------------------------
+//
+TBool SVPAudioUtility::SetDtmfPriorityL( CMceAudioStream& aAudioStream )
+    {
+    SVPDEBUG1( "SVPAudioUtility::SetDtmfPriorityL In" );
+    
+    const RPointerArray<CMceAudioCodec>& codecs = aAudioStream.Codecs();
+    TInt codCount( codecs.Count() );
+    
+    // loop through codecs in in stream
+    while ( codCount )
+        {
+        codCount--;
+        
+        SVPDEBUG2( "SVPAudioUtility::SetDtmfPriorityL, round: %d", codCount );
+        
+        // Check if codec is DTMF, note the return values of CompareF
+        if( !codecs[ codCount ]->SdpName().CompareF( KTELEVENT ) )
+            {
+            SVPDEBUG1( "SVPAudioUtility::SetDtmfPriorityL ETrue" );
+            
+            SVPDEBUG2( "SVPAudioUtility::SetDtmfPriorityL curr.prio: %d",
+                codecs[codCount]->MMFPriority() )
+            SVPDEBUG2( "SVPAudioUtility::SetDtmfPriorityL curr.pref: 0x%x",
+                codecs[codCount]->MMFPriorityPreference() )
+            
+            // Set the priorities.
+            codecs[ codCount ]->SetMMFPriorityL( KAudioPriorityDTMFString );
+            codecs[ codCount ]->SetMMFPriorityPreferenceL( KAudioDTMFString );
+            return ETrue;
+            }
+        }
+    
+    SVPDEBUG1( "SVPAudioUtility::SetDtmfPriorityL EFalse" );
+    return EFalse;
+    }
+
+// ---------------------------------------------------------------------------
+// SVPAudioUtility::SetAudioCodecPrioritiesL
+// ---------------------------------------------------------------------------
+//
+void SVPAudioUtility::SetAudioCodecPrioritiesL(
+    CMceAudioStream& aAudioStream,
+    TUint aAudioPref )
+    {
+    SVPDEBUG2( "SVPAudioUtility::SetAudioCodecPrioritiesL aAudioPref: 0x%x",
+        aAudioPref );
+    
+    const RPointerArray<CMceAudioCodec>& codecs = aAudioStream.Codecs();
+    TInt codCount( codecs.Count() );
+    
+    // loop through codecs in in stream
+    while ( codCount )
+        {
+        codCount--;
+        
+        SVPDEBUG2( "SVPAudioUtility::SetAudioCodecPrioritiesL, round: %d",
+            codCount );
+        
+        // Handle only real audio codecs.
+        if( codecs[ codCount ]->SdpName().CompareF( KTELEVENT ) )
+            {
+            SVPDEBUG2( "SVPAudioUtility::SetAudioCodecPrioritiesL curr.prio: %d",
+                codecs[codCount]->MMFPriority() )
+            SVPDEBUG2( "SVPAudioUtility::SetAudioCodecPrioritiesL curr.pref: 0x%x",
+                codecs[codCount]->MMFPriorityPreference() )
+                
+            // Priority is always the same for VoIP.
+            codecs[ codCount ]->SetMMFPriorityL( KAudioPriorityPhoneCall );
+            codecs[ codCount ]->SetMMFPriorityPreferenceL( aAudioPref );
+            }
+        } 
+    }
+
+// ---------------------------------------------------------------------------
+// SVPAudioUtility::SetAudioCodecPrioritiesL
+// ---------------------------------------------------------------------------
+//
+void SVPAudioUtility::SetAudioStreamPrioritiesL(
+    CMceMediaStream& aMediaStream,
+    CMceMediaStream& aBoundStream )
+    {
+    SVPDEBUG1( "SVPAudioUtility::SetAudioStreamPrioritiesL In" );
+    
+    if ( KMceAudio != aMediaStream.Type() ||
+         KMceAudio != aBoundStream.Type() )
+        {
+        SVPDEBUG1( "SVPAudioUtility::SetAudioStreamPrioritiesL KErrArgument" );
+        SVPDEBUG2( "SVPAudioUtility::SetAudioStreamPrioritiesL media.Type: %u",
+            aMediaStream.Type() );
+        SVPDEBUG2( "SVPAudioUtility::SetAudioStreamPrioritiesL bound.Type: %u",
+            aBoundStream.Type() );
+        
+        User::Leave( KErrArgument );
+        }
+    // else stream types are OK, thus we proceed.
+    
+    // Set the codec MMF priorities here, first get the audiostreams.
+    CMceAudioStream& stream = static_cast<CMceAudioStream&>( aMediaStream );
+    CMceAudioStream& bound = static_cast<CMceAudioStream&>( aBoundStream );
+    
+    if ( SVPAudioUtility::IsDownlinkStream( stream ) )
+        {
+        SVPAudioUtility::SetPriorityCodecValuesL( stream, bound );
+        }
+    else
+        {
+        SVPAudioUtility::SetPriorityCodecValuesL( bound, stream );
+        }
+    
+    SVPDEBUG1( "SVPAudioUtility::SetAudioStreamPrioritiesL Out" );
+    }
+
+// ---------------------------------------------------------------------------
+// SVPAudioUtility::EnableSpeakerSinkL
+// ---------------------------------------------------------------------------
+//
+void SVPAudioUtility::EnableSpeakerSinkL( 
+    const RPointerArray< CMceMediaSink >& aSink )
+    {
+    TInt snkCount( aSink.Count() );
+    while ( snkCount )
+        {
+        snkCount--;
+        if ( KMceSpeakerSink == aSink[ snkCount ]->Type() && 
+             !aSink[ snkCount ]->IsEnabled() )
+            {
+            SVPDEBUG1( "SVPAudioUtility::EnableSpeakerSinkL Speaker found" );
+            
+            aSink[ snkCount ]->EnableL();
+            
+            SVPDEBUG1( "SVPAudioUtility::EnableSpeakerSinkL Speaker ENABLED" );
+            }
+        } 
+    }
+    
+// ---------------------------------------------------------------------------
+// SVPAudioUtility::DisableSpeakerSinkL
+// ---------------------------------------------------------------------------
+//
+void SVPAudioUtility::DisableSpeakerSinkL( 
+    const RPointerArray< CMceMediaSink >& aSink )
+    {
+    TInt snkCount( aSink.Count() );
+    while ( snkCount )
+        {
+        snkCount--;
+        if ( KMceSpeakerSink == aSink[ snkCount ]->Type() &&
+             aSink[ snkCount ]->IsEnabled() )
+            {
+            SVPDEBUG1( "SVPAudioUtility::DisableSpeakerSinkL Speaker found" );
+            
+            aSink[ snkCount ]->DisableL();
+            
+            SVPDEBUG1( "SVPAudioUtility::DisableSpeakerSinkL Speaker DISABLED" );
+            }
+        } 
+    }
+
+// ---------------------------------------------------------------------------
+// SVPAudioUtility::EnableMicSourceL
+// ---------------------------------------------------------------------------
+//
+void SVPAudioUtility::EnableMicSourceL( CMceMediaSource& aMicSource )
+    {            
+    if ( KMceMicSource == aMicSource.Type() && !aMicSource.IsEnabled() )
+        {
+        SVPDEBUG1("SVPAudioUtility::EnableMicSourceL Mic found");
+        
+        aMicSource.EnableL();
+        
+        SVPDEBUG1("SVPAudioUtility::EnableMicSourceL Mic ENABLED");
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// SVPAudioUtility::DisableMicSourceL
+// ---------------------------------------------------------------------------
+//
+void SVPAudioUtility::DisableMicSourceL( CMceMediaSource& aMicSource )
+    {
+    if ( KMceMicSource == aMicSource.Type() && aMicSource.IsEnabled() )
+        {
+        SVPDEBUG1( "SVPAudioUtility::DisableMicSourceL Mic found" );
+        
+        aMicSource.DisableL();
+        
+        SVPDEBUG1( "SVPAudioUtility::DisableMicSourceL Mic DISABLED" );
+        }
+    }
+    
+// ---------------------------------------------------------------------------
+// SVPAudioUtility::EnableSpeakerSinksL
+// ---------------------------------------------------------------------------
+//
+void SVPAudioUtility::EnableSpeakerSinksL(
+    const RPointerArray< CMceMediaStream >& aStreams )
+    {
+    SVPDEBUG1("SVPAudioUtility::EnableSpeakerSinksL In");
+    
+    TInt index( aStreams.Count() );
+    while( index-- )
+        {
+        if ( KMceAudio == aStreams[ index ]->Type() )
+            {
+            EnableSpeakerSinkL( aStreams[ index ]->Sinks() );
+            }
+        
+        if ( KMceAudio == aStreams[ index ]->BoundStreamL().Type() )
+            {
+            EnableSpeakerSinkL( aStreams[ index ]->BoundStreamL().Sinks() );
+            }
+        }
+    
+    SVPDEBUG1("SVPAudioUtility::EnableSpeakerSinksL Out");
+    }
+
+// ---------------------------------------------------------------------------
+// SVPAudioUtility::DisableMicSourceL
+// ---------------------------------------------------------------------------
+//
+void SVPAudioUtility::DisableMicSourceL( CMceMediaStream& aStream )
+    {
+    SVPDEBUG1("SVPAudioUtility::DisableMicSourceL CMceMediaStream In");
+    
+    CMceMediaSource* source = NULL;
+    source = aStream.Source();
+    if ( source )
+        {
+        SVPDEBUG1("SVPAudioUtility::DisableMicSourceL aStream");
+        
+        DisableMicSourceL( *source );
+        }
+    
+    if ( aStream.BoundStream() )
+        {
+        source = aStream.BoundStreamL().Source();
+        if ( source )
+            {
+            SVPDEBUG1("SVPAudioUtility::DisableMicSourceL BoundStream");
+            
+            DisableMicSourceL( *source );
+            }
+        }
+        
+    SVPDEBUG1("SVPAudioUtility::DisableMicSourceL CMceMediaStream Out");
+    }
+
+// ---------------------------------------------------------------------------
+// SVPAudioUtility::FindCodec
+// ---------------------------------------------------------------------------
+//
+CMceAudioCodec* SVPAudioUtility::FindCodec( CMceAudioStream& aAudiostream,
+    const TDesC8& aCodecname )
+    {
+    SVPDEBUG1("SVPAudioUtility::FindCodec In");
+    
+    const RPointerArray<CMceAudioCodec>& codecs = aAudiostream.Codecs();
+    TInt codecCount = codecs.Count();
+    while ( codecCount )
+        {
+        codecCount--;
+        if ( !codecs[codecCount]->SdpName().CompareF( aCodecname ) )
+            {
+            SVPDEBUG1("SVPAudioUtility::SVPAudioUtility Codec found");
+            
+            return codecs[codecCount];
+            }
+        }
+    
+    SVPDEBUG1("SVPAudioUtility::FindCodec Out NULL");
+    return NULL;
+    }
+
+// ---------------------------------------------------------------------------
+// SVPAudioUtility::RemoveCodecL
+// ---------------------------------------------------------------------------
+//
+void SVPAudioUtility::RemoveCodecL( CMceAudioStream& aAudiostream,
+    const TDesC8& aCodecname )
+    {
+    SVPDEBUG1("SVPAudioUtility::RemoveCodecL In");
+    
+    CMceAudioCodec* codec = SVPAudioUtility::FindCodec( aAudiostream,
+        aCodecname );
+    
+    while ( codec )
+        {
+        SVPDEBUG1("SVPAudioUtility::RemoveCodecL Removing");
+        
+        aAudiostream.RemoveCodecL( *codec );
+        codec = SVPAudioUtility::FindCodec( aAudiostream, aCodecname );
+        }
+    
+    SVPDEBUG1("SVPAudioUtility::RemoveCodecL Out");
+    }
+
+// ---------------------------------------------------------------------------
+// SVPAudioUtility::MmfPriorityUpdateNeededL
+// ---------------------------------------------------------------------------
+//
+TBool SVPAudioUtility::MmfPriorityUpdateNeededL(
+    const RPointerArray<CMceMediaStream>& aStreams )
+    {
+    SVPDEBUG1( "SVPAudioUtility::MmfPriorityUpdateNeededL In" )
+    
+    // We need to check if DTMF codec is found and then check uplink stream
+    // MMF priorities.
+    // 1) If DTMF codec is found and uplink stream codecs have preference
+    //    KSVPAudioPrefAudioUplinkOobDtmf no update is needed.
+    // 2) If DTMF codec is not found and uplink stream codecs have preference
+    //    KSVPAudioPrefAudioUplinkIbDtmf no update is needed.
+    // 3) In other cases we need to do MMF preference/priority update.
+    
+    // In order to do this we need to find uplink audio streams, check whether
+    // the stream has DTMF codec and then check which MMF preference the codec
+    // codec has. We may have multiple streams, but for simplicity sake if
+    // we find just one stream needing priority/preference update, we return
+    // ETrue as update need.
+    TInt strmCount( aStreams.Count() );
+    
+    SVPDEBUG2( "SVPAudioUtility::MmfPriorityUpdateNeededL strmCount: %d",
+        strmCount )
+    
+    while ( strmCount )
+        {
+        SVPDEBUG2( "SVPAudioUtility::MmfPriorityUpdateNeededL tb checked",
+            strmCount )
+        
+        strmCount--;
+        
+        // Basic assertions. Streams have to be KMceAudio and 'main' stream
+        // must have a bound stream.
+        __ASSERT_ALWAYS( KMceAudio == aStreams[strmCount]->Type(),
+            User::Leave( KErrArgument ) );
+        __ASSERT_ALWAYS( aStreams[strmCount]->BoundStream(),
+            User::Leave( KErrArgument ) );
+        __ASSERT_ALWAYS( KMceAudio == aStreams[strmCount]->BoundStreamL().Type(),
+            User::Leave( KErrArgument ) );
+        
+        // Now that we are clear from the asserts, we can safely do the casts
+        // and find the uplink stream for priority/preference checking.
+        CMceAudioStream* audioStream =
+            static_cast<CMceAudioStream*>( aStreams[strmCount] );
+        CMceAudioStream& boundStream =
+            static_cast<CMceAudioStream&>( audioStream->BoundStreamL() );
+        
+        CMceAudioStream* uplinkStream = NULL;
+        
+        if ( !IsDownlinkStream( *audioStream ) )
+            {
+            SVPDEBUG1( "SVPAudioUtility::MmfPriorityUpdateNeededL main is uplink" )
+            
+            uplinkStream = audioStream;
+            }
+        else if ( !IsDownlinkStream( boundStream ) )
+            {
+            SVPDEBUG1( "SVPAudioUtility::MmfPriorityUpdateNeededL bound is uplink" )
+            
+            uplinkStream = &boundStream;
+            }
+        
+        // Next assert handles the missing else branch.
+        __ASSERT_ALWAYS( uplinkStream, User::Leave( KErrNotFound ) );
+        
+        TBool res = MmfPriorityUpdateNeededL( *uplinkStream );
+        if ( res )
+            {
+            SVPDEBUG1( "SVPAudioUtility::MmfPriorityUpdateNeededL ETrue" )
+            return ETrue;
+            }
+        }
+    
+    SVPDEBUG1( "SVPAudioUtility::MmfPriorityUpdateNeededL EFalse" )
+    return EFalse;
+    }
+
+// ---------------------------------------------------------------------------
+// SVPAudioUtility::MmfPriorityUpdateNeededL
+// ---------------------------------------------------------------------------
+//
+TBool SVPAudioUtility::MmfPriorityUpdateNeededL(
+    CMceAudioStream& aUplinkStream )
+    {
+    SVPDEBUG1( "SVPAudioUtility::MmfPriorityUpdateNeededL (stream) In" )
+    
+    // Check which uplink preference we need to have based whether DTMF codec
+    // is part of the codec list.
+    TUint uplinkPreference = 0;
+    if ( FindCodec( aUplinkStream, KTELEVENT ) )
+        {
+        SVPDEBUG1( "SVPAudioUtility::MmfPriorityUpdateNeededL (stream) DTMF OB" )
+        
+        uplinkPreference = KSVPAudioPrefUplinkOobDtmf;
+        }
+    else
+        {
+        SVPDEBUG1( "SVPAudioUtility::MmfPriorityUpdateNeededL (stream) DTMF IB" )
+        
+        uplinkPreference = KSVPAudioPrefUplinkIbDtmf;
+        }
+    
+    // Given stream must have at least one codec in order to do the priority /
+    // preference check. This function is private and called inside, thus this
+    // assertion just adds to the checks done in caller.
+    const RPointerArray<CMceAudioCodec>& codecs = aUplinkStream.Codecs();
+    TInt codecCount = codecs.Count();
+    
+    SVPDEBUG2( "SVPAudioUtility::MmfPriorityUpdateNeededL (stream) codecCount: %d",
+        codecCount )
+    
+    __ASSERT_ALWAYS( codecCount, User::Leave( KErrArgument ) );
+    
+    while( codecCount )
+        {
+        SVPDEBUG2( "SVPAudioUtility::MmfPriorityUpdateNeededL (stream) tb checked: %d",
+            codecCount )
+        
+        codecCount--;
+        
+        SVPDEBUG2( "SVPAudioUtility::MmfPriorityUpdateNeededL curr.prio: %d",
+                codecs[codecCount]->MMFPriority() )
+        SVPDEBUG2( "SVPAudioUtility::MmfPriorityUpdateNeededL curr.pref: 0x%x",
+                codecs[codecCount]->MMFPriorityPreference() )
+        
+        // Do not include DTMF codec into the preference check. Note CompareF
+        // return value also, 0 means match.
+        if ( codecs[codecCount]->SdpName().CompareF( KTELEVENT ) &&
+            uplinkPreference != codecs[codecCount]->MMFPriorityPreference() )
+            {
+            SVPDEBUG1( "SVPAudioUtility::MmfPriorityUpdateNeededL (stream) ETrue" )
+            
+            return ETrue;
+            }
+        
+        // else preferences match, ne-ext please!!!
+        }
+    
+    SVPDEBUG1( "SVPAudioUtility::MmfPriorityUpdateNeededL (stream) EFalse" )
+    return EFalse;
+    }
+
+// ---------------------------------------------------------------------------
+// SVPAudioUtility::DtmfActionCapableSession
+// ---------------------------------------------------------------------------
+//
+TBool SVPAudioUtility::DtmfActionCapableSession(
+    const CSVPSessionBase& aSession )
+    {
+    if ( aSession.HasHoldController() &&
+         ESVPConnected == aSession.HoldController().HoldState() )
+        {
+        SVPDEBUG1( "SVPAudioUtility::DtmfActionCapableSession ETrue 1" )
+        
+        return ETrue;
+        }
+    else if ( !aSession.HasHoldController() )
+        {
+        SVPDEBUG1( "SVPAudioUtility::DtmfActionCapableSession ETrue 2" )
+        
+        return ETrue;
+        }
+    else
+        {
+        SVPDEBUG1( "SVPAudioUtility::DtmfActionCapableSession EFalse" )
+        
+        return EFalse;
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// Check DTMF capability of emergency session
+// ---------------------------------------------------------------------------
+//
+TBool SVPAudioUtility::DtmfActionCapableSession(
+    const CSVPEmergencySession& aSession )
+    {
+    if ( aSession.HasHoldController() &&
+         ESVPConnected == aSession.HoldController().HoldState() )
+        {
+        SVPDEBUG1( "SVPAudioUtility::DtmfActionCapableSession ETrue 1" )
+        
+        return ETrue;
+        }
+    else if ( !aSession.HasHoldController() )
+        {
+        SVPDEBUG1( "SVPAudioUtility::DtmfActionCapableSession ETrue 2" )
+        
+        return ETrue;
+        }
+    else
+        {
+        SVPDEBUG1( "SVPAudioUtility::DtmfActionCapableSession EFalse" )
+        
+        return EFalse;
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// SVPAudioUtility::DtmfActionCapableStream
+// ---------------------------------------------------------------------------
+//
+TBool SVPAudioUtility::DtmfActionCapableStream(
+    const CMceMediaStream& aStream )
+    {
+    // We used to check for source's DtmfAvailable and DtmfActive attributes,
+    // but those are IPC calls which are not preferred for DTMF's real-time
+    // nature. Thus leaving those out and letting the server return us a
+    // error code if those attributes are not correct for DTMF sending
+    // actually does the same thing but improves performance.
+    // Thus what once was three IPC calls is now just one.
+    TBool ret = EFalse;
+    CMceMediaSource* source = aStream.Source();
+    
+#ifdef _DEBUG
+    SVPDEBUG2( "SVPAudioUtility::DtmfActionCapableStream type: %d", aStream.Type() )
+    SVPDEBUG2( "SVPAudioUtility::DtmfActionCapableStream source: 0x%x", source )
+    if ( source )
+        {
+        SVPDEBUG2( "SVPAudioUtility::DtmfActionCapableStream enabled: %d", source->IsEnabled() )
+        }
+#endif
+    
+    if ( KMceAudio == aStream.Type() && source && source->IsEnabled() )
+        {
+        ret = ETrue;
+        }
+    
+    SVPDEBUG2( "SVPAudioUtility::DtmfActionCapableStream ret: %d", ret )
+    
+    return ret;
+    }
+