diff -r f742655b05bf -r d38647835c2e sipvoipprovider/src/svpaudioutility.cpp --- /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 +#include +#include +#include +#include +#include +#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 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& 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& 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( aMediaStream ); + CMceAudioStream& bound = static_cast( 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& 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& 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( aStreams[strmCount] ); + CMceAudioStream& boundStream = + static_cast( 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& 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; + } +