diff -r f742655b05bf -r d38647835c2e sipvoipprovider/src/svpsessionbase.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sipvoipprovider/src/svpsessionbase.cpp Wed Sep 01 12:29:57 2010 +0100 @@ -0,0 +1,3294 @@ +/* +* Copyright (c) 2006-2010 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: Session base class for SVP MO and MT sessions. Contains methods +* common for SVP MO and MT sessions. +* +*/ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include // for mute + +#include "svpsessionbase.h" +#include "svpholdcontroller.h" +#include "svptransfercontroller.h" +#include "svptransferstatecontext.h" +#include "svptimer.h" +#include "svpsipconsts.h" +#include "svpuriparser.h" +#include "svpaudioutility.h" +#include "svpvolumeobserver.h" +#include "svplogger.h" +#include "svputility.h" +#include "svprtpobserver.h" +#include "svppropertywatch.h" +#include "svpdtmfeventgenerator.h" + + +// Local Consts +const TInt KMaxTimerValueMO = 4000; +const TInt KMinTimerValueMO = 2100; +const TInt KMaxTimerValueMT = 2000; +const TInt KMinTimerValueMT = 10; + +const TInt KRandomDividerOne = 1000000; +const TInt KRandomDividerTwo = 1000; + +const TInt KMaxPhoneVolume = 10; + +// --------------------------------------------------------------------------- +// CSVPSessionBase::CSVPSessionBase +// --------------------------------------------------------------------------- +// +CSVPSessionBase::CSVPSessionBase( TMceTransactionDataContainer& aContainer, + MSVPSessionObserver& aObserver, CSVPUtility& aSVPUtility, + CSVPRtpObserver& aRtpObserver ) : + iSVPUtility( aSVPUtility ), + iRtpObserver( aRtpObserver ), + iContainer( aContainer ), + iObserver( aObserver ), + iErrorInULandDLFirstTime ( ETrue ), + iEarlyMediaOngoing ( EFalse ) + { + } + +// --------------------------------------------------------------------------- +// CSVPSessionBase::~CSVPSessionBase +// --------------------------------------------------------------------------- +// +CSVPSessionBase::~CSVPSessionBase() + { + SVPDEBUG1( "SVPSessionBase::~CSVPSessionBase In" ) + + delete iCallParameters; + + delete iHoldController; + + iObserver.RemoveFromArray( *this ); + + delete iSession; + + StopTimers(); + + iTimers.Close(); + + delete iRecipient; + + delete iDisplayName; + + delete iTransferController; + + delete iMutePropertyWatch; + + delete iVolObserver; + + delete iFromHeader; + + delete iToHeader; + + delete iCallId; + + delete iCSeqHeader; + + delete iEventGenerator; + + delete (iTempSecSession != iSession ? iTempSecSession : NULL ); + + delete iDtmfString; + + SVPDEBUG1( "CSVPSessionBase::~CSVPSessionBase Out" ) + } + +// --------------------------------------------------------------------------- +// CSVPSessionBase::ReleaseTempSecure +// --------------------------------------------------------------------------- +// +void CSVPSessionBase::ReleaseTempSecure() + { + delete iTempSecSession; + iTempSecSession = NULL; + } + +// --------------------------------------------------------------------------- +// CSVPSessionBase::Session +// --------------------------------------------------------------------------- +// +const CMceSession& CSVPSessionBase::Session() const + { + return *iSession; + } + +// --------------------------------------------------------------------------- +// CSVPSessionBase::StartTimerL +// --------------------------------------------------------------------------- +// +void CSVPSessionBase::StartTimerL( TInt aMilliSeconds, TInt aTimerId ) + { + SVPDEBUG1( "CSVPSessionBase::StartTimerL In" ) + + CSVPTimer* timer = CSVPTimer::NewL( *this, aTimerId ); + CleanupStack::PushL( timer ); + timer->SetTime( aMilliSeconds ); + iTimers.AppendL( timer ); + CleanupStack::Pop( timer ); + + SVPDEBUG1( "CSVPSessionBase::StartTimerL Out" ) + } + +// --------------------------------------------------------------------------- +// CSVPSessionBase::StopTimers +// --------------------------------------------------------------------------- +// +void CSVPSessionBase::StopTimers() + { + SVPDEBUG1( "CSVPSessionBase::StopTimers In" ) + + while ( iTimers.Count() ) + { + iTimers[0]->Stop(); + delete iTimers[0]; + iTimers.Remove( 0 ); + } + + SVPDEBUG1( "CSVPSessionBase::StopTimers Out" ) + } + +// --------------------------------------------------------------------------- +// CSVPSessionBase::ReinviteCrossoverTime +// --------------------------------------------------------------------------- +// +TInt CSVPSessionBase::ReinviteCrossoverTime() + { + SVPDEBUG1( "CSVPSessionBase::ReinviteCrossoverTime In" ) + + TInt maxValue( 0 ); + TInt minValue( 0 ); + + if ( IsMobileOriginated() ) + { + minValue = KMinTimerValueMO; + maxValue = KMaxTimerValueMO; + } + else + { + minValue = KMinTimerValueMT; + maxValue = KMaxTimerValueMT; + } + + TInt timerValue( 0 ); + TTime time; + time.HomeTime(); + TInt64 seed( time.Int64() ); + + for ( TInt i = 0; i < ( maxValue - minValue ); i++ ) + { + TInt random = Math::Rand( seed ); + TReal random2 = ( TReal )random / KRandomDividerOne; + TInt random3 = ( TInt )( minValue * random2 ) / KRandomDividerTwo; + + if ( minValue <= random3 && minValue >= random3 ) + { + timerValue = random3; + break; + } + } + + SVPDEBUG2("CSVPSessionBase::ReinviteCrossoverTime Out return: %d", timerValue ) + return timerValue; + } + +// --------------------------------------------------------------------------- +// CSVPSessionBase::StopTimer +// --------------------------------------------------------------------------- +// +void CSVPSessionBase::StopTimer( TInt aTimerId ) + { + SVPDEBUG2( "CSVPSessionBase::StopTimer In, Timer -- ID: %d", aTimerId ) + + // Find the timer and delete it. + for ( TInt t = 0; t < iTimers.Count(); ) + { + if ( iTimers[ t ] ->Id() == aTimerId ) + { + iTimers[t]->Stop(); + delete iTimers[ t ]; + iTimers.Remove( t ); + } + else + { + t++; + } + } + + SVPDEBUG1( "CSVPSessionBase::StopTimer Out" ) + } + +// --------------------------------------------------------------------------- +// CSVPSessionBase::TimedOut +// --------------------------------------------------------------------------- +// +void CSVPSessionBase::TimedOut( TInt aTimerId ) + { + SVPDEBUG1( "CSVPSessionBase::TimedOut In" ) + + // Find the timer and delete it. + for ( TInt t = 0; t < iTimers.Count(); ) + { + if ( iTimers[ t ] ->Id() == aTimerId ) + { + delete iTimers[ t ]; + iTimers.Remove( t ); + } + else + { + t++; + } + } + + if ( KSVPInviteTimerExpired == aTimerId ) + { + // INVITE timer expired, notify client + SVPDEBUG1( "CSVPSessionBase::TimedOut Invite timer expired, callback" ) + ExecCbErrorOccurred( ECCPErrorNotResponding ); + + // send cancel + TRAPD( errCancel, static_cast< CMceOutSession* >( iSession )->CancelL() ); + + if ( errCancel ) + { + SVPDEBUG2( "CSVPSessionBase::TimedOut Cancel: %d", errCancel ) + } + + ExecCbCallStateChanged( MCCPCallObserver::ECCPStateDisconnecting ); + + TRAPD( errTimer, StartTimerL( KSVPTerminatingTime, KSVPRemoteEndDiedExpired )); + if ( errTimer ) + { + SVPDEBUG2("CSVPSessionBase::No Answer timer leave with error code %d", + errTimer ) + } + } + + if ( KSVPTerminationTimerExpired == aTimerId ) + { + // Renew terminating timer to keep session alive when incoming + // transfer ongoing, not longer than max default expire time (120s) + if ( IsIncomingTransfer() && + !IsAttended() && + iTerminatingRepeat < KSVPDefaultExpiresTime ) + { + SVPDEBUG2( "CSVPSessionBase::TimedOut UnAtte case iTerminatingRepeat = %d", + iTerminatingRepeat ) + + // Continue timeout time if the new session of the + // incoming transfer not yet established + iTerminatingRepeat = iTerminatingRepeat + + KSVPTerminatingTime / KSVPMilliSecondCoefficient; + + TRAPD( errTimer, StartTimerL( KSVPTerminatingTime, + KSVPTerminationTimerExpired ) ); + + if ( errTimer ) + { + SVPDEBUG2( "CSVPSessionBase::TimedOut Termination leave with code %d", + errTimer ) + } + } + else + { + SVPDEBUG1( "CSVPSessionBase::TimedOut Termination timer, callback" ) + ExecCbCallStateChanged( MCCPCallObserver::ECCPStateIdle ); + } + } + + if ( KSVPRemoteEndDiedExpired == aTimerId ) + { + SVPDEBUG1( "CSVPSessionBase::TimedOut remote end died, callback" ) + // disconnecting state callback sent before timer started + ExecCbCallStateChanged( MCCPCallObserver::ECCPStateIdle ); + } + + if ( KSVPHangUpTimerExpired == aTimerId ) + { + SVPDEBUG1( "CSVPSessionBase::TimedOut HangUp timer expired, callback" ) + // disconnecting state callback sent before timer started + ExecCbCallStateChanged( MCCPCallObserver::ECCPStateIdle ); + } + + if ( KSVPExpiresTimeExpired == aTimerId ) + { + SVPDEBUG1( "CSVPSessionBase::TimedOut expires timer expired" ) + // send 487 + TRAPD( err, static_cast( iSession )->RespondL( + KSVPRequestTerminatedReason, KSVPRequestTerminatedVal ) ); + + if ( err ) + { + // sending response failed + // not serious because session is put to idle state anyway + } + // event is needed in upper level for correct bubble and log handling + ExecCbCallEventOccurred( MCCPCallObserver::ECCPRemoteTerminated ); + // idle can be sent directly without disconnecting state + ExecCbCallStateChanged( MCCPCallObserver::ECCPStateIdle ); + } + + if ( KSVPHoldTimerExpired == aTimerId || + KSVPResumeTimerExpired == aTimerId ) + { + if ( iHoldController ) + { + SVPDEBUG1( "CSVPSessionBase::TimedOut - Hold/Resume request Expired" ) + + iHoldController->TimedOut(); + TInt contErr = iHoldController->ContinueHoldProcessing( *iSession ); + + if ( KSVPResumeTimerExpired == aTimerId && + CMceSession::EEstablished == iSession->State() ) + { + // MCE state error prevents cancelling session; go to terminating + SVPDEBUG1( "CSVPSessionBase::TimedOut - MCE established" ) + HandleSessionStateChanged( *iSession ); + SVPDEBUG1( "CSVPSessionBase::TimedOut - hold/resume done" ) + } + else + { + TRAPD( cancelErr, static_cast( iSession )->CancelL() ); + + if ( cancelErr ) + { + // This removes compile warnings; no need for other error + // handling + SVPDEBUG2( "CSVPSessionBase::TimedOut - Hold/Resume, Err %i", + cancelErr ) + } + } + + SVPDEBUG2( "CSVPSessionBase::TimedOut - Hold/Resume Handled, Err %i", + contErr ) + } + } + + if ( KSVPReferTimerExpired == aTimerId ) + { + // Refer timeout + SVPDEBUG1( "CSVPSessionBase::TimedOut Transfer/Refer timer expired" ) + + if ( iTransferController ) + { + // Inform application about the error + ExecCbErrorOccurred( ECCPTransferFailed ); + // Terminate transfer + iTransferController->TerminateTransfer(); + } + } + + if ( KSVPReInviteTimerExpired == aTimerId ) + { + if ( iHoldController ) + { + SVPDEBUG1( "CSVPSessionBase::TimedOut - ReInvite timer expired" ) + iHoldController->RetryHoldRequest( iSession ); + } + } + + if ( KSVPICMPErrorTimerExpired == aTimerId ) + { + TBool bothStreamsDisabled ( ETrue ); + TRAP_IGNORE( bothStreamsDisabled = IsBothStreamsDisabledL() ); + if ( bothStreamsDisabled ) + { + SVPDEBUG1( "CSVPSessionBase::TimedOut Error In UL and DL \ + NOT First Time! -> Start Terminating Timer and BYE" ) + // notify CCE about the error & bring session down. + ExecCbErrorOccurred( ECCPErrorConnectionError ); + ExecCbCallStateChanged( MCCPCallObserver::ECCPStateDisconnecting ); + + TRAP_IGNORE( StartTimerL( KSVPTerminatingTime, KSVPRemoteEndDiedExpired ) ); + } + else + { + SVPDEBUG1( "CSVPSessionBase::TimedOut UpLink or DownLink \ + is not Disabled! -> No Terminating Timer needed, all is OK!" ) + } + SetErrorInULandDLFirstTime( ETrue ); + } + + if ( KSVPSinkResumeICMPErrorTimerExpired == aTimerId || + KSVPSourceResumeICMPErrorTimerExpired == aTimerId ) + { + if ( iHoldController ) + { + // ICMP errors in resume disables RTP sink, try to enable it: + SVPDEBUG1( "CSVPSessionBase::TimedOut - Resume ICMP error timer expired" ) + TRAPD( refreshErr, HoldController().RefreshHoldStateL() ); + if ( refreshErr ) + { + // Removes compile warnings; no other error handling + SVPDEBUG2( "CSVPSessionBase::TimedOut - refreshHold err %d", refreshErr ) + } + } + } + + SVPDEBUG1( "CSVPSessionBase::TimedOut Out" ) + } + +// --------------------------------------------------------------------------- +// CSVPSessionBase::SessionStateChanged +// --------------------------------------------------------------------------- +// +void CSVPSessionBase::SessionStateChanged( TInt aStatusCode ) + { + SVPDEBUG2( "CSVPSessionBase::SessionStateChanged In, aStatusCode= %d", aStatusCode ) + SVPDEBUG2( "CSVPSessionBase::SessionStateChanged iSession->State()= %d", iSession->State() ) + + TInt status = aStatusCode; + TCCPError err = iSVPUtility.GetCCPError( status, iTone ); + + // On error call voip event logger with original status, 3xx are not logged. + if ( ECCPErrorNone != err && ECCPErrorNotReached != err ) + { + TRAP_IGNORE( iSVPUtility.LogVoipEventL( aStatusCode, + iSipProfileId, RemoteParty(), CSeqHeader() ) ); + } + + #ifdef _DEBUG // UDEB build + + TRAPD( trapErr, SessionStateChangedL( aStatusCode, err, status ) ); + SVPDEBUG2( "CSVPSessionBase::SessionStateChanged trapErr: %d", trapErr ) + + #else // UREL build + + TRAP_IGNORE( SessionStateChangedL( aStatusCode, err, status ) ); + + #endif // _DEBUG + + SVPDEBUG1( "CSVPSessionBase::SessionStateChanged Out" ) + } + +// --------------------------------------------------------------------------- +// CSVPSessionBase::InitializePropertyWatchingL +// --------------------------------------------------------------------------- +// +void CSVPSessionBase::InitializePropertyWatchingL() + { + SVPDEBUG1( "CSVPSessionBase::InitializePropertyWatchingL In" ) + + // create property watcher for watching mute P&S property changes + iMutePropertyWatch = CSVPPropertyWatch::NewL( + *this, KPSUidTelMicrophoneMuteStatus, KTelMicrophoneMuteState ); + + // check initial mute value + TInt value( EPSTelMicMuteOff ); + RProperty::Get( KPSUidTelMicrophoneMuteStatus, + KTelMicrophoneMuteState, value ); + + // check initial mute status + if( EPSTelMicMuteOff == value ) + { + SVPDEBUG1( "CSVPSessionBase::InitializePropertyWatchingL Initally mute: OFF" ) + } + else if ( EPSTelMicMuteOn == value ) + { + SVPDEBUG1( "CSVPSessionBase::InitializePropertyWatchingL Initially Mute: ON" ) + // if mute is initially on, we must mute the audio + ValueChangedL( KTelMicrophoneMuteState, EPSTelMicMuteOn ); + } + + // create instance of volume obsever + iVolObserver = CSVPVolumeObserver::NewL( *this ); + + SVPDEBUG1( "CSVPSessionBase::InitializePropertyWatchingL Out" ) + } + +// --------------------------------------------------------------------------- +// CSVPSessionBase::ExecCbErrorOccurred +// --------------------------------------------------------------------------- +// +TInt CSVPSessionBase::ExecCbErrorOccurred( TCCPError aError ) + { + SVPDEBUG2( "CSVPSessionBase::ExecCbErrorOccurred In, aError= %d", aError ) + + TInt status = KErrNotFound; + + if ( iCCPSessionObserver ) + { + status = KErrNone; + iCCPSessionObserver->ErrorOccurred( aError, this ); + } + + SVPDEBUG2( "CSVPSessionBase::ExecCbErrorOccurred Out return=%d", status ) + return status; + } + +// --------------------------------------------------------------------------- +// CSVPSessionBase::ExecCbCallStateChanged +// --------------------------------------------------------------------------- +// +TInt CSVPSessionBase::ExecCbCallStateChanged( + MCCPCallObserver::TCCPCallState aNewState ) + { + SVPDEBUG2( "CSVPSessionBase::ExecCbCallStateChanged In, aNewState= %d", aNewState ) + SVPDEBUG2( "CSVPSessionBase::ExecCbCallStateChanged iSessionState= %d", iSessionState ) + + TInt status = (TInt) aNewState; + + if ( !( (TInt) MCCPCallObserver::ECCPStateIdle > status ) ) + { + // state transition OK + iSessionState = (MCCPCallObserver::TCCPCallState) status; + + if ( iCCPSessionObserver ) + { + status = KErrNone; + iCCPSessionObserver->CallStateChanged( iSessionState, this ); + } + } + + SVPDEBUG2( "CSVPSessionBase::ExecCbCallStateChanged Out return=%d", status ) + return status; + } + +// --------------------------------------------------------------------------- +// CSVPSessionBase::ExecCbCallEventOccurred +// --------------------------------------------------------------------------- +// +TInt CSVPSessionBase::ExecCbCallEventOccurred( + MCCPCallObserver::TCCPCallEvent aEvent ) + { + SVPDEBUG2( "CSVPSessionBase::ExecCbCallEventOccurred In, aEvent= %d", aEvent ) + + TInt status = KErrNotFound; + + if ( iCCPSessionObserver ) + { + status = KErrNone; + iCCPSessionObserver->CallEventOccurred( aEvent, this ); + } + + SVPDEBUG2( "CSVPSessionBase::ExecCbCallEventOccurred Out, return= %d", status ) + return status; + } + +// --------------------------------------------------------------------------- +// CSVPSessionBase::ExecCbSsEventOccurred +// --------------------------------------------------------------------------- +// +TInt CSVPSessionBase::ExecCbSsEventOccurred( + MCCPSsObserver::TCCPSsCallForwardEvent aEvent ) + { + SVPDEBUG2( "CSVPSessionBase::ExecCbSsEventOccurred In, aEvent= %d", aEvent ) + + TInt status = KErrNotFound; + + if ( iCCPSsObserver ) + { + status = KErrNone; + iCCPSsObserver->CallForwardEventOccurred( aEvent, *iRecipient ); + } + + SVPDEBUG2( "CSVPSessionBase::ExecCbSsEventOccurred Out return=%d", status ) + return status; + } + + +//---------------------------------------------------------------------------- +//CSVPSessionBase::SetSsObserver +//---------------------------------------------------------------------------- +// +void CSVPSessionBase::SetSsObserver( const MCCPSsObserver& aObserver ) + { + SVPDEBUG1( "CSVPSessionBase::SetSsObserver In" ) + + iCCPSsObserver = const_cast< MCCPSsObserver* >( &aObserver ); + + SVPDEBUG1( "CSVPSessionBase::SetSsObserver In" ) + } + +//---------------------------------------------------------------------------- +//CSVPSessionBase::GetSsObserver +//---------------------------------------------------------------------------- +// +const MCCPSsObserver& CSVPSessionBase::GetSsObserver( ) + { + SVPDEBUG1( "CSVPSessionBase::GetSsObserver" ) + + return *iCCPSsObserver; + } + +// --------------------------------------------------------------------------- +// CSVPSessionBase::SetDtmfObserver +// --------------------------------------------------------------------------- +// +void CSVPSessionBase::SetDtmfObserver( const MCCPDTMFObserver& aObserver ) + { + SVPDEBUG1( "CSVPSessionBase::SetDtmfObserver In" ) + + iCCPDtmfObserver = const_cast< MCCPDTMFObserver* >( &aObserver ); + + SVPDEBUG1( "CSVPSessionBase::SetDtmfObserver Out" ) + } + +// --------------------------------------------------------------------------- +// CSVPSessionBase::DtmfObserver +// --------------------------------------------------------------------------- +// +const MCCPDTMFObserver& CSVPSessionBase::DtmfObserver() + { + SVPDEBUG1( "CSVPSessionBase::DtmfObserver" ) + + return *iCCPDtmfObserver; + } + +// --------------------------------------------------------------------------- +// CSVPSessionBase::EventStateChanged +// --------------------------------------------------------------------------- +// +TInt CSVPSessionBase::EventStateChanged( CMceEvent& aEvent, TInt aStatusCode ) + { + SVPDEBUG1( "CSVPSessionBase::EventStateChanged In" ) + + TInt err( KErrNone ); + + if ( iTransferController ) + { + TRAP( err, iTransferController->HandleEventStateChangedL( + aEvent, aStatusCode ) ); + + if ( KSVPErrTransferInProgress == err ) + { + // Transfer allready in progress + SVPDEBUG1( "CSVPSessionBase::EventStateChanged, KSVPErrTransferInProgress" ) + } + else if ( KErrNone != err ) + { + SVPDEBUG2( "CSVPSessionBase::EventStateChanged, err = %d", err ) + // Inform application about the error + ExecCbErrorOccurred( ECCPTransferFailed ); + } + } + else + { + // Inform application about the error + ExecCbErrorOccurred( ECCPTransferFailed ); + err = KSVPErrTransferErrorBase; + } + + SVPDEBUG2( "CSVPSessionBase::EventStateChanged Out return=%d", err ) + return err; + } + +// --------------------------------------------------------------------------- +// CSVPSessionBase::NotifyReceived +// --------------------------------------------------------------------------- +// +void CSVPSessionBase::NotifyReceived( CMceEvent& aEvent, + TMceTransactionDataContainer* aContainer ) + { + SVPDEBUG1( "CSVPSessionBase::NotifyReceived In" ) + + if ( iTransferController ) + { + TRAPD( err, iTransferController->NotifyReceivedL( + aEvent, aContainer ) ); + + if ( KErrNone != err ) + { + // Inform application about the error + ExecCbErrorOccurred( ECCPTransferFailed ); + } + } + else + { + // Inform application about the error + ExecCbErrorOccurred( ECCPTransferFailed ); + } + + SVPDEBUG1( "CSVPSessionBase::NotifyReceived Out" ) + } + +// --------------------------------------------------------------------------- +// CSVPSessionBase::ReferStateChanged +// --------------------------------------------------------------------------- +// +void CSVPSessionBase::ReferStateChanged( CMceRefer& aRefer, TInt aStatusCode ) + { + SVPDEBUG1( "CSVPSessionBase::ReferStateChangedL In" ) + + if ( iTransferController ) + { + TRAPD( err, iTransferController->HandleReferStateChangeL( + aRefer, aStatusCode ) ); + + if ( KErrNone != err ) + { + // Inform application about the error + ExecCbErrorOccurred( ECCPTransferFailed ); + } + } + else + { + // Inform application about the error + ExecCbErrorOccurred( ECCPTransferFailed ); + } + + SVPDEBUG1( "CSVPSessionBase::ReferStateChangedL Out" ) + } + +// --------------------------------------------------------------------------- +// CSVPSessionBase::MceTransactionDataContainer +// --------------------------------------------------------------------------- +// +TMceTransactionDataContainer& CSVPSessionBase::MceTransactionDataContainer() + { + return iContainer; + } + +// --------------------------------------------------------------------------- +// CSVPSessionBase::IncomingReferL +// --------------------------------------------------------------------------- +// +void CSVPSessionBase::IncomingReferL( CMceInRefer* aRefer, + const TDesC8& aReferTo, TMceTransactionDataContainer* aContainer ) + { + SVPDEBUG1( "CSVPSessionBase::IncomingReferL In" ) + + if ( !iTransferController ) + { + // Create new transfercontroller + iTransferController = CSVPTransferController::NewL( + iSession, this, iContainer, *this ); + } + + iTransferController->IncomingReferL( aRefer, aReferTo, aContainer ); + + SVPDEBUG1( "CSVPSessionBase::IncomingReferL Out" ) + } + +// --------------------------------------------------------------------------- +// CSVPSessionBase::IsMceRefer +// --------------------------------------------------------------------------- +// +TBool CSVPSessionBase::IsMceRefer( CMceRefer& aRefer ) + { + if ( iTransferController ) + { + return iTransferController->IsMceRefer( aRefer ); + } + else + { + return EFalse; + } + } + +// --------------------------------------------------------------------------- +// CSVPSessionBase::IsAttended +// --------------------------------------------------------------------------- +// +TBool CSVPSessionBase::IsAttended() + { + if ( iTransferController ) + { + return iTransferController->IsAttended(); + } + else + { + return EFalse; + } + } + +// --------------------------------------------------------------------------- +// CSVPSessionBase::SetTransferDataL +// --------------------------------------------------------------------------- +// +void CSVPSessionBase::SetTransferDataL( CDesC8Array* aUserAgentHeaders, + TInt aSecureStatus ) + { + SVPDEBUG1( "CSVPSessionBase::SetTransferDataL In" ) + + if ( iTransferController ) + { + iTransferController->SetTransferDataL( + aUserAgentHeaders, aSecureStatus ); + } + + SVPDEBUG1( "CSVPSessionBase::SetTransferDataL Out" ) + } + +// --------------------------------------------------------------------------- +// CSVPSessionBase::SendNotify +// --------------------------------------------------------------------------- +// +void CSVPSessionBase::SendNotify( TInt aStatusCode ) + { + SVPDEBUG1( "CSVPSessionBase::SendNotify In" ) + + if ( iTransferController ) + { + #ifdef _DEBUG + + TRAPD( err, iTransferController->SendNotifyL( aStatusCode ) ); + SVPDEBUG2("CSVPSessionBase::SendNotify SendNotifyL err: %d", err ) + + #else + + TRAP_IGNORE( iTransferController->SendNotifyL( aStatusCode ) ); + + #endif // _DEBUG + } + + SVPDEBUG1( "CSVPSessionBase::SendNotify Out" ) + } + +// --------------------------------------------------------------------------- +// CSVPSessionBase::IsIncomingTransfer +// --------------------------------------------------------------------------- +// +TBool CSVPSessionBase::IsIncomingTransfer() + { + if ( iTransferController ) + { + return iTransferController->IsIncomingTransfer(); + } + else + { + return EFalse; + } + } + +// --------------------------------------------------------------------------- +// CSVPSessionBase::TransferTarget +// --------------------------------------------------------------------------- +// +const TDesC& CSVPSessionBase::TransferTarget() const + { + SVPDEBUG1( "CSVPSessionBase::TransferTarget" ) + + if ( iTransferController ) + { + return iTransferController->TransferTarget(); + } + else + { + return KNullDesC; + } + } + +// ----------------------------------------------------------------------------- +// CSVPSessionBase::SetFromHeader +// ----------------------------------------------------------------------------- +// +TInt CSVPSessionBase::SetFromHeader( const TDesC8& aFromHeader ) + { + SVPDEBUG1( "CSVPSessionBase::SetFromHeader" ) + + delete iFromHeader; + iFromHeader = NULL; + + TRAPD( err, iFromHeader = aFromHeader.AllocL() ); + return err; + } + +// ----------------------------------------------------------------------------- +// CSVPSessionBase::FromHeader +// ----------------------------------------------------------------------------- +// +TDesC8* CSVPSessionBase::FromHeader() + { + return iFromHeader; + } + +// ----------------------------------------------------------------------------- +// CSVPSessionBase::SetToHeader +// ----------------------------------------------------------------------------- +// +TInt CSVPSessionBase::SetToHeader( const TDesC8& aToHeader ) + { + SVPDEBUG1( "CSVPSessionBase::SetToHeader" ) + + delete iToHeader; + iToHeader = NULL; + + TRAPD( err, iToHeader = aToHeader.AllocL() ); + return err; + } + +// ----------------------------------------------------------------------------- +// CSVPSessionBase::ToHeader +// ----------------------------------------------------------------------------- +// +TDesC8* CSVPSessionBase::ToHeader() + { + return iToHeader; + } + +// ----------------------------------------------------------------------------- +// CSVPSessionBase::SetCallId +// ----------------------------------------------------------------------------- +// +TInt CSVPSessionBase::SetCallId( const TDesC8& aCallId ) + { + SVPDEBUG1( "CSVPSessionBase::SetCallId" ) + + delete iCallId; + iCallId = NULL; + + TRAPD( err, iCallId = aCallId.AllocL() ); + return err; + } + +// ----------------------------------------------------------------------------- +// CSVPSessionBase::CallId +// ----------------------------------------------------------------------------- +// +TDesC8* CSVPSessionBase::CallId() + { + return iCallId; + } + +// ----------------------------------------------------------------------------- +// CSVPSessionBase::SetCSeqHeader +// ----------------------------------------------------------------------------- +// +TInt CSVPSessionBase::SetCSeqHeader( const TDesC8& aCSeq ) + { + SVPDEBUG1( "CSVPSessionBase::SetCSeqHeader In" ) + + delete iCSeqHeader; + iCSeqHeader = NULL; + + TRAPD( err, iCSeqHeader = HBufC::NewL( aCSeq.Length() ) ); + iCSeqHeader->Des().Copy( aCSeq ); + + // Check "CSeq:" and remove it from the beginning if exists + if ( 0 == iCSeqHeader->Des().FindF( KSVPCSeqPrefix ) ) + { + // CSeq: is in the beginning of the string, remove it and 1 blank + iCSeqHeader->Des().Delete( 0, KSVPCSeqPrefixLength + 1 ); + } + + // Check/remove the sequence number and the blank + const TInt spacePosition = iCSeqHeader->Des().Find( KSVPSpace2 ); + + if ( spacePosition != KErrNotFound ) + { + iCSeqHeader->Des().Delete( 0, spacePosition + 1 ); + } + + SVPDEBUG2( "CSVPSessionBase::SetCSeqHeader Out return=%d", err ) + return err; + } + +// --------------------------------------------------------------------------- +// CSVPSessionBase::CSeqHeader +// --------------------------------------------------------------------------- +// +const TDesC& CSVPSessionBase::CSeqHeader() const + { + SVPDEBUG1( "CSVPSessionBase::CSeqHeader In" ) + + if ( iCSeqHeader ) + { + SVPDEBUG1( "CSVPSessionBase::CSeqHeader Out" ) + return *iCSeqHeader; + } + else + { + SVPDEBUG1( "CSVPSessionBase::CSeqHeader Out KNullDesC" ) + return KNullDesC; + } + } + +// --------------------------------------------------------------------------- +// CSVPSessionBase::AddObserverL +// --------------------------------------------------------------------------- +// +void CSVPSessionBase::AddObserverL( const MCCPCallObserver& aObserver ) + { + SVPDEBUG1( "CSVPSessionBase::AddObserverL In" ) + + // set session observer + // only one observer used at a time, replaces current one + iCCPSessionObserver = const_cast< MCCPCallObserver* >( &aObserver ); + + SVPDEBUG1( "CSVPSessionBase::AddObserverL Out" ) + } + +// --------------------------------------------------------------------------- +// CSVPSessionBase::GetCCPSessionObserver +// --------------------------------------------------------------------------- +// +MCCPCallObserver& CSVPSessionBase::GetCCPSessionObserver() + { + SVPDEBUG1( "CSVPSessionBase::GetCCPSessionObserver" ) + // get session observer + return *iCCPSessionObserver; + } + +// --------------------------------------------------------------------------- +// CSVPSessionBase::RemoveObserver +// --------------------------------------------------------------------------- +// +TInt CSVPSessionBase::RemoveObserver( const MCCPCallObserver& /*aObserver*/ ) + { + return KErrNotSupported; + } + +// --------------------------------------------------------------------------- +// CSVPSessionBase::InbandDtmfEventOccurred +// --------------------------------------------------------------------------- +// +void CSVPSessionBase::InbandDtmfEventOccurred( TSVPDtmfEvent aEvent ) + { + SVPDEBUG1( "CSVPSessionBase::InbandDtmfEventOccurred In" ) + SVPDEBUG2( "CSVPSessionBase::InbandDtmfEventOccurred aEvent:%d", aEvent ) + + switch ( aEvent ) + { + case ESvpDtmfSendStarted: + { + DtmfObserver(). + HandleDTMFEvent( MCCPDTMFObserver::ECCPDtmfSequenceStart, + KErrNone, + iDtmfLex.Peek() ); + break; + } + + case ESvpDtmfSendStopped: + { + DtmfObserver().HandleDTMFEvent( + MCCPDTMFObserver::ECCPDtmfSequenceStop, + KErrNone, + iDtmfLex.Get() ); + break; + } + + case ESvpDtmfSendCompleted: + { + DtmfObserver().HandleDTMFEvent( + MCCPDTMFObserver::ECCPDtmfStringSendingCompleted, + KErrNone, + iDtmfLex.Peek() ); + break; + } + + default: + { + SVPDEBUG1( "CSVPSessionBase::InbandDtmfEventOccurred Default" ) + break; + } + } + + SVPDEBUG1( "CSVPSessionBase::InbandDtmfEventOccurred Out" ) + } + + +// --------------------------------------------------------------------------- +// CSVPSessionBase::ConstructAudioStreamsL +// --------------------------------------------------------------------------- +// +void CSVPSessionBase::ConstructAudioStreamsL() + { + SVPDEBUG1( "CSVPSessionBase::ConstructAudioStreamsL In" ) + + // OUT STREAM + // create "audio out" stream first, puts audioOutStream to cleanupstack + CMceAudioStream* audioOutStream = CMceAudioStream::NewLC(); // CS: 1 + // create mic source + CMceMicSource* mic = CMceMicSource::NewLC(); // CS: 2 + // set source for "audio out" stream, in this case it's microphone + // there can be only one source at a time. + audioOutStream->SetSourceL( mic ); + // pop mic from cleanupstack + CleanupStack::Pop( mic ); // CS: 1 + // create rtp sink for mic + CMceRtpSink* rtpSink = CMceRtpSink::NewLC(); // CS: 2 + audioOutStream->AddSinkL( rtpSink ); + CleanupStack::Pop( rtpSink ); // CS: 1 + + // IN STREAM + // create "audio in" stream + CMceAudioStream* audioInStream = CMceAudioStream::NewLC(); // CS: 2 + // create rtp source for "audio in" stream + CMceRtpSource* rtpSource = CMceRtpSource::NewLC( + KSvpJitterBufferLength, KSvpJitterBufferThreshold, + KSvpStandbyTimerInMillisecs ); // CS: 3 + audioInStream->SetSourceL( rtpSource ); + // pop rtp source from cleanupstack + CleanupStack::Pop( rtpSource ); // CS: 2 + // create speaker sink for "audio in" stream + CMceSpeakerSink* speakerSink = CMceSpeakerSink::NewLC(); // CS: 3 + audioInStream->AddSinkL( speakerSink ); + // pop speaker from cleanupstack + CleanupStack::Pop( speakerSink ); // CS: 2 + + // Bind "audio out" stream to "audio in" stream. Ownership of the stream + // is transferred thus we must pop the instream from CS. + audioOutStream->BindL( audioInStream ); + CleanupStack::Pop( audioInStream ); // CS: 1 + + // Add stream to session. Note that the ownership is transferred thus + // we pop the audioOutStream in this phase. + iSession->AddStreamL( audioOutStream ); + CleanupStack::Pop( audioOutStream ); // CS: 0 + + // establish Old way hold support + iSession->SetModifierL( KMceMediaDirection, + KMceMediaDirectionWithAddress ); + + // preconditions are set so that long negotiation is taken in to use + // when establishing secure call + if ( SecureMandatory() || SecurePreferred() ) + { + iSession->SetModifierL( KMceSecPreconditions, + KMcePreconditionsE2ESupported ); + } + else + { + // else modify preconditions off + iSession->SetModifierL( KMcePreconditions, + KMcePreconditionsNotUsed ); + } + + SVPDEBUG2( "CSVPSessionBase::ConstructAudioStreamsL audioInStream codec count: %d", + audioInStream->Codecs().Count() ) + SVPDEBUG2( "CSVPSessionBase::ConstructAudioStreamsL audioOutStream codec count: %d", + audioOutStream->Codecs().Count() ) + + // add codecs to audiostream + iSVPUtility.SetAudioCodecsMOL( + iVoIPProfileId, *audioInStream, iKeepAliveValue ); + + // set same local media port from InStream to OutStream + audioOutStream->SetLocalMediaPortL( audioInStream->LocalMediaPort() ); + iSVPUtility.UpdateJitterBufferSizeL( *rtpSource ); + + // set MMF priorities and preferences to codecs + SVPDEBUG1( "CSVPSessionBase::ConstructAudioStreamsL Set MMF priorities" ) + iSVPUtility.SetDtmfMode( SVPAudioUtility::SetPriorityCodecValuesL( + *audioInStream, *audioOutStream ) ); + + SVPDEBUG1( "CSVPSessionBase::ConstructAudioStreamsL Out" ) + } + +// --------------------------------------------------------------------------- +// CSVPSessionBase::HangUp +// --------------------------------------------------------------------------- +// +TInt CSVPSessionBase::HangUp() + { + SVPDEBUG1( "CSVPSessionBase::HangUp In" ) + + TInt err( KErrNone ); + + if ( CMceSession::EEstablished == iSession->State() ) + { + SVPDEBUG1( "CSVPSessionBase::HangUp() TerminateL" ) + + TRAP( err, iSession->TerminateL() ); + + if ( !err ) + { + ExecCbCallStateChanged( MCCPCallObserver::ECCPStateDisconnecting ); + + // IsAttended() and different timer values needed for + // attended transfer when there is also one waiting call queued + // and ringing tone for queued session needs to be played + TInt timerID = 0; + TInt delay = 0; + + if ( IsAttended() ) + { + delay = KSVPTerminatingTime; + timerID = KSVPTerminationTimerExpired; + } + else{ + delay = KSVPMoHangupTerminatingTime; + timerID = KSVPHangUpTimerExpired; + } + + TRAPD( errTimer, StartTimerL( delay, timerID ) ); + + if ( errTimer ) + { + SVPDEBUG2("CSVPSessionBase::HangUp timer leave with error code %d", + errTimer ) + } + else + { + iAlreadyTerminating = ETrue; + } + } + } + else + { + SVPDEBUG2( "CSVPSessionBase::HangUp() Wrong state: %d", iSession->State() ) + + StopTimers(); + ExecCbCallStateChanged( MCCPCallObserver::ECCPStateIdle ); + } + + SVPDEBUG2( "CSVPSessionBase::HangUp Out return=%d", err ) + return err; + } + +// --------------------------------------------------------------------------- +// CSVPSessionBase::Hold +// --------------------------------------------------------------------------- +// +TInt CSVPSessionBase::Hold() + { + SVPDEBUG1( "CSVPSessionBase::Hold In" ) + + TInt err( KErrNone ); + + if ( CMceSession::EEstablished == iSession->State() ) + { + if ( !iHoldController ) + { + TRAP( err, iHoldController = + CSVPHoldController::NewL( *iSession, + iContainer, + this, + IsMobileOriginated() ) ); + if ( KErrNone != err ) + { + return err; + } + } + + iHoldController->Muted( iMuted ); + err = iHoldController->HoldSession( iSession ); + + if ( KErrNone != err ) + { + ExecCbErrorOccurred( ECCPLocalHoldFail ); + } + else + { + TRAP( err, StartTimerL( KSVPHoldExpirationTime, + KSVPHoldTimerExpired ) ); + + SVPDEBUG2( "CSVPSessionBase::Hold - Started Expire timer, err %i", + err ) + } + } + + else + { + ExecCbErrorOccurred( ECCPLocalHoldFail ); + } + + SVPDEBUG2( "CSVPSessionBase::Hold Out return=%d", err ) + return err; + } + +// --------------------------------------------------------------------------- +// CSVPSessionBase::Resume +// --------------------------------------------------------------------------- +// +TInt CSVPSessionBase::Resume() + { + SVPDEBUG1( "CSVPSessionBase::Resume In" ) + + TInt err( KErrNone ); + + if ( !iHoldController ) + { + TRAP( err, iHoldController = CSVPHoldController::NewL( + *iSession, iContainer, this, IsMobileOriginated() ) ); + + if ( KErrNone != err ) + { + SVPDEBUG2( "CSVPSessionBase::Resume Out return(err)=%d", err ) + return err; + } + } + + iHoldController->Muted( iMuted ); + err = iHoldController->ResumeSession( iSession ); + + if ( KErrNone != err ) + { + ExecCbErrorOccurred( ECCPLocalResumeFail ); + } + else + { + TRAP( err, StartTimerL( KSVPResumeExpirationTime, + KSVPResumeTimerExpired ) ); + SVPDEBUG2("CSVPSessionBase::Resume - Started Expire timer, err %i", + err ); + } + + SVPDEBUG2( "CSVPSessionBase::Resume Out return=%d", err ) + return err; + } + +// --------------------------------------------------------------------------- +// CSVPSessionBase::IncomingRequest +// --------------------------------------------------------------------------- +// +TInt CSVPSessionBase::IncomingRequest( CMceInSession& aUpdatedSession ) + { + SVPDEBUG1( "CSVPSessionBase::IncomingRequest In" ) + + // Check if own request is ongoing + if ( iHoldController ) + { + iHoldController->CheckCrossOver( *this ); + } + + if ( &aUpdatedSession ) + { + //Because there is an update we have to discard everything about ICMP -3 + StopTimer ( KSVPICMPErrorTimerExpired ); + if ( !IsErrorInULandDLFirstTime() ) + { + SetErrorInULandDLFirstTime( ETrue ); + } + + TInt err( KErrNone ); + + if ( !iHoldController ) + { + TRAP( err, iHoldController = CSVPHoldController::NewL( + *iSession, iContainer, this, IsMobileOriginated() ) ); + + if ( KErrNone != err ) + { + return err; + } + + TBool sessionUpdateOngoing = ETrue; + + // Most likely a hold case, MT needs to set the keepalive + TRAP_IGNORE( SetRtpKeepAliveL( &aUpdatedSession, + sessionUpdateOngoing ) ); + } + + SVPDEBUG2( "CSVPSessionBase::IncomingRequest iSession: 0x%x", iSession ) + + // Update changed session to the transfercontroller + if ( iTransferController ) + { + iTransferController->SetMceSessionObject( &aUpdatedSession ); + } + + iHoldController->Muted( iMuted ); + + TInt status = iHoldController->IncomingRequest( &aUpdatedSession ); + SVPDEBUG2( "CSVPSessionBase::IncomingRequest Out return=%d", status ) + return status; + } + else + { + SVPDEBUG1( "CSVPSessionBase::IncomingRequest Out illegal aUpdatedSession" ) + return KErrArgument; + } + } + +// --------------------------------------------------------------------------- +// CSVPSessionBase::HoldController +// --------------------------------------------------------------------------- +// +CSVPHoldController& CSVPSessionBase::HoldController() const + { + return *iHoldController; + } + +// --------------------------------------------------------------------------- +// CSVPSessionBase::HasHoldController +// --------------------------------------------------------------------------- +// +TBool CSVPSessionBase::HasHoldController() const + { + if ( iHoldController ) + { + return ETrue; + } + else + { + return EFalse; + } + } + +// --------------------------------------------------------------------------- +// CSVPSessionBase::HandleSessionStateChanged +// --------------------------------------------------------------------------- +// +void CSVPSessionBase::HandleSessionStateChanged( CMceSession& aSession ) + { + SVPDEBUG1( "CSVPSessionBase::HandleSessionStateChanged In" ) + + + if ( iHoldController ) + { + if ( iHoldController->HoldInProgress() ) + { + SVPDEBUG1( "CSVPSessionBase::HandleSessionStateChanged HoldInProgress" ) + + StopTimers(); + iHoldController->Muted( iMuted ); + TInt err = iHoldController->ContinueHoldProcessing( aSession ); + + if ( KErrNone != err ) + { + SVPDEBUG2( "CSVPSessionBase::HandleSessionStateChanged, err: %d", err ) + ExecCbErrorOccurred( ECCPLocalHoldFail ); + } + } + else if ( iHoldController->ResumeFailed() ) + { + // Must terminate session; timer expired + SVPDEBUG1( "CSVPSessionBase::HandleSessionStateChanged Resume failed - Terminating" ) + + TRAPD( err, iSession->TerminateL() ); + + if ( !err ) + { + SVPDEBUG1( "CSVPSessionBase::HandleSessionStateChanged Disconnecting" ) + ExecCbCallStateChanged( MCCPCallObserver::ECCPStateDisconnecting ); + + TRAP( err, StartTimerL( KSVPMoHangupTerminatingTime, + KSVPHangUpTimerExpired ) ); + + if ( KErrNone != err ) + { + SVPDEBUG2("CSVPSessionBase::HandleSessionStateChanged Hangup-timer error %d", + err ) + } + } + else + { + SVPDEBUG1( "CSVPSessionBase::HandleSessionStateChanged - Term ERROR!" ) + } + } + else if ( iHoldController->HoldFailed() ) + { + // Hold timer expired; no actions needed here + SVPDEBUG1( "CSVPSessionBase::HandleSessionStateChanged: Hold request failed - nothing to do" ) + } + else + { + SVPDEBUG1( "CSVPSessionBase::HandleSessionStateChanged - else" ) + } + } + + SVPDEBUG1( "CSVPSessionBase::HandleSessionStateChanged Out" ) + } + +// --------------------------------------------------------------------------- +// CSVPSessionBase::HandleStreamStateChange +// --------------------------------------------------------------------------- +// +void CSVPSessionBase::HandleStreamStateChange( CMceMediaStream& aStream ) + { + SVPDEBUG2( "CSVPSessionBase::HandleStreamStateChange(aStream) stream state= %d", + aStream.State() ) + SVPDEBUG2( "CSVPSessionBase::HandleStreamStateChange(aStream) stream type= %d", + aStream.Type() ) + SVPDEBUG2( "CSVPSessionBase::HandleStreamStateChange(aStream) session state= %d", + aStream.Session()->State() ) + + if ( CMceMediaStream::EStreaming == aStream.State() && + CMceSession::EOffering == aStream.Session()->State() ) + { + SVPDEBUG1( "CSVPSessionBase::HandleStreamStateChange(aStream) early media started" ) + ExecCbCallEventOccurred( MCCPCallObserver::ECCCSPEarlyMediaStarted ); + iEarlyMediaOngoing = ETrue; + } + TBool bothStreamsDisabled ( ETrue ); + TRAP_IGNORE( bothStreamsDisabled = IsBothStreamsDisabledL() ); + if ( bothStreamsDisabled && + CMceSession::EEstablished == aStream.Session()->State() && + IsErrorInULandDLFirstTime() ) + { + SetErrorInULandDLFirstTime( EFalse ); + TRAP_IGNORE( StartTimerL( KSVPICMPErrorTime, KSVPICMPErrorTimerExpired ) ) + } + else if ( !bothStreamsDisabled && !IsErrorInULandDLFirstTime() ) + { + SetErrorInULandDLFirstTime( ETrue ); + StopTimer ( KSVPICMPErrorTimerExpired ); + } + SVPDEBUG1( "CSVPSessionBase::HandleStreamStateChange(aStream) Out" ) + } + +// --------------------------------------------------------------------------- +// CSVPSessionBase::HandleStreamStateChange +// --------------------------------------------------------------------------- +// +void CSVPSessionBase::HandleStreamStateChange( CMceMediaStream& aStream, + CMceMediaSink& aSink ) + { + SVPDEBUG1( "CSVPSessionBase::HandleStreamStateChange(aStream,aSink) In" ) + + CMceSession::TState sessionState = CMceSession::ETerminated; + + if ( &aStream ) + { + SVPDEBUG2( "CSVPSessionBase::HandleStreamStateChange(aStream,aSink) stream state=%d", + aStream.State() ) + SVPDEBUG2( "CSVPSessionBase::HandleStreamStateChange(aStream,aSink) stream type=%d", + aStream.Type() ) + } + + if ( &aStream && aStream.Session() ) + { + sessionState = aStream.Session()->State(); + SVPDEBUG2( "CSVPSessionBase::HandleStreamStateChange(aStream,aSink) session state=%d", sessionState ) + } + + if ( &aSink ) + { + SVPDEBUG2( "CSVPSessionBase::HandleStreamStateChange(aStream,aSink) is sink enabled=%d", + aSink.IsEnabled() ) + + if ( HasHoldController() && ESVPConnected == HoldController().HoldState() && + !aSink.IsEnabled() && CMceSession::EEstablished == sessionState ) + { + // Hold state is connected but sink is disabled -> try enable after a while + SVPDEBUG1( "CSVPSessionBase::HandleStreamStateChange - Resume ICMP, Sink" ) + TRAP_IGNORE( StartTimerL( KSVPSinkResumeICMPErrorTime, KSVPSinkResumeICMPErrorTimerExpired ) ) + } + + else if ( !HasHoldController() && !aSink.IsEnabled() && CMceSession::EEstablished == sessionState && + CMceMediaStream::EDisabled == aStream.State() ) + { + // Not a hold case, mediaStream and sink is disabled -> try enable after a while + SVPDEBUG1( "CSVPSessionBase::HandleStreamStateChange - ICMP, Sink and MediaStream" ) + if ( !IsSessionMuted() ) + { + SVPDEBUG1( "CSVPSessionBase::HandleStreamStateChange - ICMP, Sink not enabled -> enable" ) + aSink.EnableL(); + } + } + } + + SVPDEBUG1( "CSVPSessionBase::HandleStreamStateChange(aStream,aSink) Out" ) + } + +// --------------------------------------------------------------------------- +// CSVPSessionBase::HandleStreamStateChange +// --------------------------------------------------------------------------- +// +void CSVPSessionBase::HandleStreamStateChange( CMceMediaStream& aStream, + CMceMediaSource& aSource ) + { + SVPDEBUG1( "CSVPSessionBase::HandleStreamStateChange(aStream,aSource) In" ) + + CMceSession::TState sessionState = CMceSession::ETerminated; + + if ( &aStream ) + { + SVPDEBUG2( "CSVPSessionBase::HandleStreamStateChange(aStream,aSource) stream state=%d", + aStream.State() ) + SVPDEBUG2( "CSVPSessionBase::HandleStreamStateChange(aStream,aSource) stream type=%d", + aStream.Type() ) + } + + if ( &aStream && aStream.Session() ) + { + sessionState = aStream.Session()->State(); + SVPDEBUG2( "CSVPSessionBase::HandleStreamStateChange(aStream,aSource) session state=%d", sessionState ) + } + + if ( &aSource ) + { + SVPDEBUG2( "CSVPSessionBase::HandleStreamStateChange(aStream,aSource) is source enabled=%d", + aSource.IsEnabled() ) + + if ( HasHoldController() && ESVPConnected == HoldController().HoldState() && + !aSource.IsEnabled() && CMceSession::EEstablished == sessionState ) + { + // Hold state is connected but source is disabled -> try enable after a while + SVPDEBUG1( "CSVPSessionBase::HandleStreamStateChange - Resume ICMP, Source" ) + TRAP_IGNORE( StartTimerL( KSVPSourceResumeICMPErrorTime, KSVPSourceResumeICMPErrorTimerExpired ) ) + } + + else if ( !HasHoldController() && !aSource.IsEnabled() && CMceSession::EEstablished == sessionState && + CMceMediaStream::EDisabled == aStream.State() ) + { + // Not a hold case, mediaStream and source is disabled -> try enable after a while + SVPDEBUG1( "CSVPSessionBase::HandleStreamStateChange - ICMP, Source and MediaStream" ) + if ( !IsSessionMuted() ) + { + SVPDEBUG1( "CSVPSessionBase::HandleStreamStateChange - ICMP, Source not enabled -> enable" ) + aSource.EnableL(); + } + } + } + + SVPDEBUG1( "CSVPSessionBase::HandleStreamStateChange(aStream,aSource) Out" ) + } + +// --------------------------------------------------------------------------- +// CSVPSessionBase::SessionLocallyHeld, from MSVPHoldObserver +// --------------------------------------------------------------------------- +// +void CSVPSessionBase::SessionLocallyHeld() + { + SVPDEBUG1( "CSVPSessionBase::SessionLocallyHeld In" ) + + ExecCbCallStateChanged( MCCPCallObserver::ECCPStateHold ); + iRtpObserver.ResetSessionInObserving( this ); + + SVPDEBUG1( "CSVPSessionBase::SessionLocallyHeld Out" ) + } + +// --------------------------------------------------------------------------- +// CSVPSessionBase::SessionLocallyResumed, from MSVPHoldObserver +// --------------------------------------------------------------------------- +// +void CSVPSessionBase::SessionLocallyResumed() + { + SVPDEBUG1( "CSVPSessionBase::SessionLocallyResumed In" ) + + ExecCbCallStateChanged( MCCPCallObserver::ECCPStateConnected ); + iRtpObserver.ResetSessionInObserving( this ); + + SVPDEBUG1( "CSVPSessionBase::SessionLocallyResumed Out" ) + } + +// --------------------------------------------------------------------------- +// CSVPSessionBase::SessionRemoteHeld, from MSVPHoldObserver +// --------------------------------------------------------------------------- +// +void CSVPSessionBase::SessionRemoteHeld() + { + SVPDEBUG1( "CSVPSessionBase::SessionRemoteHeld In" ) + + ExecCbCallEventOccurred( MCCPCallObserver::ECCPRemoteHold ); + iRtpObserver.ResetSessionInObserving( this ); + + SVPDEBUG1( "CSVPSessionBase::SessionRemoteHeld Out" ) + } + +// --------------------------------------------------------------------------- +// CSVPSessionBase::SessionRemoteResumed, from MSVPHoldObserver +// --------------------------------------------------------------------------- +// +void CSVPSessionBase::SessionRemoteResumed() + { + SVPDEBUG1( "CSVPSessionBase::SessionRemoteResumed In" ) + + ExecCbCallEventOccurred( MCCPCallObserver::ECCPRemoteResume ); + iRtpObserver.ResetSessionInObserving( this ); + + SVPDEBUG1( "CSVPSessionBase::SessionRemoteResumed Out" ) + } + +// --------------------------------------------------------------------------- +// CSVPSessionBase::HoldRequestFailed, from MSVPHoldObserver +// --------------------------------------------------------------------------- +// +void CSVPSessionBase::HoldRequestFailed() + { + SVPDEBUG1( "CSVPSessionBase::HoldRequestFailed In" ) + + ExecCbErrorOccurred( ECCPLocalHoldFail ); + + SVPDEBUG1( "CSVPSessionBase::HoldRequestFailed Out" ) + } + +// --------------------------------------------------------------------------- +// CSVPSessionBase::ResumeRequestFailed, from MSVPHoldObserver +// --------------------------------------------------------------------------- +// +void CSVPSessionBase::ResumeRequestFailed() + { + SVPDEBUG1( "CSVPSessionBase::ResumeRequestFailed In" ) + + ExecCbErrorOccurred( ECCPLocalResumeFail ); + + SVPDEBUG1( "CSVPSessionBase::ResumeRequestFailed Out" ) + } + +// --------------------------------------------------------------------------- +// CSVPSessionBase::RemoteParty +// --------------------------------------------------------------------------- +// +const TDesC& CSVPSessionBase::RemoteParty() const + { + delete iRecipient; + iRecipient = NULL; + + // RemotePartyL is used to handle leave situations + TRAPD( remoteErr, RemotePartyL() ); + + if ( KErrNone != remoteErr ) + { + // something went wrong, return null + SVPDEBUG2( "CSVPSessionBase::RemoteParty remoteErr=%d", remoteErr ) + return KNullDesC; + } + else + { + return *iRecipient; + } + } + +// --------------------------------------------------------------------------- +// CSVPSessionBase::RemotePartyL +// --------------------------------------------------------------------------- +// +void CSVPSessionBase::RemotePartyL() const + { + SVPDEBUG1( "CSVPSessionBase::RemotePartyL In" ) + + // fetch recipient from Mce, convert recipient to 16-bit descriptor + if ( IsMobileOriginated() ) + { + SVPDEBUG1( "CSVPSessionBase::RemotePartyL, mo case, Fetch: RECIPIENT" ) + iRecipient = HBufC::NewL( iSession->Recipient().Length() ); + iRecipient->Des().Copy( iSession->Recipient() ); + + // remove all extra parameters from recipient address + TInt index = iRecipient->Des().FindF( KSVPSemiColon ); + + if ( KErrNotFound != index ) + { + iRecipient->Des().Delete( index, iRecipient->Length() ); + // remove left bracket if exists + TInt bracketLocation = iRecipient->Locate( KSVPLeftBracket ); + if ( KErrNotFound != bracketLocation ) + { + iRecipient->Des().Delete( bracketLocation, 1 ); + } + } + + // check if anonymous address + index = iRecipient->Des().FindF( KSVPAnonymous ); + if ( KErrNotFound != index ) + { + // Anonymous address case + SVPDEBUG2( "CSVPSessionBase::RemotePartyL: Anonymous = %d", index ) + iRecipient->Des().Copy( KNullDesC ); + } + } + else + { + SVPDEBUG1( "CSVPSessionBase::RemotePartyL, mt case, Fetch: ORIGINATOR" ) + HBufC* uri = CSVPUriParser::ParseRemotePartyUriL( + iSession->Originator() ); + delete iRecipient; + iRecipient = uri; + uri = NULL; + } + + SVPDEBUG1( "CSVPSessionBase::RemotePartyL Out" ) + } + +// --------------------------------------------------------------------------- +// CSVPSessionBase::RemotePartyName +// --------------------------------------------------------------------------- +// +const TDesC& CSVPSessionBase::RemotePartyName() + { + SVPDEBUG1( "CSVPSessionBase::RemotePartyName()" ) + + HBufC* displayName = NULL; + TRAPD( err, displayName = CSVPUriParser::ParseDisplayNameL( + iSession->Originator() ) ) + + if ( err || NULL == displayName ) + { + SVPDEBUG1( "CSVPSessionBase::RemotePartyName, return KNullDesC" ) + delete displayName; + displayName = NULL; + return KNullDesC; + } + else + { + delete iDisplayName; + iDisplayName = displayName; + displayName = NULL; + return *iDisplayName; + } + } + +// --------------------------------------------------------------------------- +// CSVPSessionBase::DialledParty +// --------------------------------------------------------------------------- +// +const TDesC& CSVPSessionBase::DialledParty() const + { + SVPDEBUG1( "CSVPSessionBase::DialledParty not implemented" ) + return KNullDesC; + } + +// --------------------------------------------------------------------------- +// CSVPSessionBase::State +// --------------------------------------------------------------------------- +// +MCCPCallObserver::TCCPCallState CSVPSessionBase::State() const + { + SVPDEBUG1( "CSVPSessionBase::State In" ) + SVPDEBUG2( "CSVPSessionBase::State iSession->State()=%d", iSession->State() ) + + // ccpState can be safely initialized with StatusIdle + MCCPCallObserver::TCCPCallState ccpState = + MCCPCallObserver::ECCPStateIdle; + + switch ( iSession->State() ) + { + case CMceSession::EIdle: + { + SVPDEBUG1( "CSVPSessionBase::State EIdle received" ) + ccpState = MCCPCallObserver::ECCPStateIdle; + break; + } + case CMceSession::EOffering: + { + SVPDEBUG1( "CSVPSessionBase::State EOffering received" ) + ccpState = MCCPCallObserver::ECCPStateConnecting; + break; + } + case CMceSession::EIncoming: + { + SVPDEBUG1( "CSVPSessionBase::State EIncoming received" ) + ccpState = MCCPCallObserver::ECCPStateAnswering; + break; + } + case CMceSession::EReserving: + { + SVPDEBUG1( "CSVPSessionBase::State EReserving received" ) + ccpState = MCCPCallObserver::ECCPStateConnecting; + break; + } + case CMceSession::EAnswering: + { + SVPDEBUG1( "CSVPSessionBase::State EAnswering received" ) + ccpState = MCCPCallObserver::ECCPStateAnswering; + break; + } + case CMceSession::EProceeding: + { + SVPDEBUG1( "CSVPSessionBase::State EProceeding received" ) + ccpState = MCCPCallObserver::ECCPStateConnecting; + break; + } + case CMceSession::EEstablished: + { + SVPDEBUG1( "CSVPSessionBase::State EEstablished received" ) + ccpState = MCCPCallObserver::ECCPStateConnected; + if( iHoldController && ESVPOnHold == iHoldController->HoldState() ) + { + SVPDEBUG1( " CSVPSessionBase::State Established and holded" ) + ccpState = MCCPCallObserver::ECCPStateHold; + } + break; + } + case CMceSession::ECancelling: + { + SVPDEBUG1( "CSVPSessionBase::State ECancelling received" ) + ccpState = MCCPCallObserver::ECCPStateIdle; + break; + } + case CMceSession::ETerminating: + { + SVPDEBUG1( "CSVPSessionBase::State ETerminating received" ) + ccpState = MCCPCallObserver::ECCPStateDisconnecting; + break; + } + case CMceSession::ETerminated: + { + SVPDEBUG1( "CSVPSessionBase::State ETerminated received" ) + + if ( MCCPCallObserver::ECCPStateDisconnecting == iSessionState ) + { + SVPDEBUG1( "CSVPSessionBase::State Saving state for termination timer" ) + ccpState = MCCPCallObserver::ECCPStateDisconnecting; + } + else + { + ccpState = MCCPCallObserver::ECCPStateIdle; + } + + break; + } + default: + { + SVPDEBUG1( "CSVPSessionBase::State DEFAULT" ) + // This block should never be reached. + __ASSERT_DEBUG( EFalse, User::Panic( + KSVPName, KSVPPanicBadArgument ) ); + break; + } + } + + SVPDEBUG2( "CSVPSessionBase::State Out return=%d", ccpState ) + return ccpState; + } + +// --------------------------------------------------------------------------- +// CSVPSessionBase::GetKeepAliveTime +// --------------------------------------------------------------------------- +// +TInt CSVPSessionBase::GetKeepAliveTime() + { + return iKeepAliveValue; + } + +// --------------------------------------------------------------------------- +// CSVPSessionBase::Type +// --------------------------------------------------------------------------- +// +TUid CSVPSessionBase::Uid() const + { + return KSVPImplementationUid; + } + + +// --------------------------------------------------------------------------- +// CSVPSessionBase::Conference +// --------------------------------------------------------------------------- +// +MCCPConferenceCall* CSVPSessionBase::ConferenceProviderL( + const MCCPConferenceCallObserver& /*aObserver*/ ) + { + return NULL; + } + +// --------------------------------------------------------------------------- +// CSVPSessionBase::IsSecured +// --------------------------------------------------------------------------- +// +TBool CSVPSessionBase::IsSecured() const + { + SVPDEBUG2( "CSVPSessionBase::IsSecured: %d", iSecured ) + return iSecured; + } + +// --------------------------------------------------------------------------- +// CSVPSessionBase::IsMobileOriginated +// --------------------------------------------------------------------------- +// +TBool CSVPSessionBase::IsMobileOriginated() const + { + SVPDEBUG1( "CSVPSessionBase::IsMobileOriginated" ) + return EFalse; + } + +// --------------------------------------------------------------------------- +// CSVPSessionBase::IsCallForwarded +// --------------------------------------------------------------------------- +// +TBool CSVPSessionBase::IsCallForwarded() const + { + return EFalse; + } + +// --------------------------------------------------------------------------- +// CSVPSessionBase::Swap +// --------------------------------------------------------------------------- +// +TInt CSVPSessionBase::Swap() + { + return KErrNotSupported; + } + +// --------------------------------------------------------------------------- +// CSVPSessionBase::Caps +// --------------------------------------------------------------------------- +// +MCCPCallObserver::TCCPCallControlCaps CSVPSessionBase::Caps() const + { + SVPDEBUG1( "CSVPSessionBase::Caps return ECCPCapsPSCall" ) + return MCCPCallObserver::ECCPCapsPSCall; + } + +// --------------------------------------------------------------------------- +// CSVPSessionBase::Release +// --------------------------------------------------------------------------- +// +TInt CSVPSessionBase::Release() + { + return KErrNotSupported; + } + +// --------------------------------------------------------------------------- +// CSVPSessionBase::Dial +// --------------------------------------------------------------------------- +// +TInt CSVPSessionBase::Dial() + { + return KErrNotSupported; + } + +// --------------------------------------------------------------------------- +// CSVPSessionBase::Answer +// --------------------------------------------------------------------------- +// +TInt CSVPSessionBase::Answer() + { + return KErrNotSupported; + } + +// --------------------------------------------------------------------------- +// CSVPSessionBase::Cancel +// --------------------------------------------------------------------------- +// +TInt CSVPSessionBase::Cancel() + { + return KErrNotSupported; + } + +// --------------------------------------------------------------------------- +// CSVPSessionBase::Reject +// --------------------------------------------------------------------------- +// +TInt CSVPSessionBase::Reject() + { + return KErrNotSupported; + } + +// --------------------------------------------------------------------------- +// CSVPSessionBase::Queue +// --------------------------------------------------------------------------- +// +TInt CSVPSessionBase::Queue() + { + return KErrNotSupported; + } + +// --------------------------------------------------------------------------- +// CSVPSessionBase::Ringing +// --------------------------------------------------------------------------- +// +TInt CSVPSessionBase::Ringing() + { + return KErrNotSupported; + } + +// --------------------------------------------------------------------------- +// CSVPSessionBase::TransferProvider +// --------------------------------------------------------------------------- +// +MCCPTransferProvider* CSVPSessionBase::TransferProviderL( + const MCCPTransferObserver& aObserver ) + { + SVPDEBUG1( "CSVPSessionBase::TransferProviderL In" ) + + if ( !iTransferController ) + { + iTransferController = CSVPTransferController::NewL( + iSession, + this, + iContainer, + *this ); + iTransferController->AddObserverL( aObserver ); + } + + SVPDEBUG1( "CSVPSessionBase::TransferProviderL Out" ) + return iTransferController; + } + +// --------------------------------------------------------------------------- +// CSVPSessionBase::ForwardProviderL +// --------------------------------------------------------------------------- +// +MCCPForwardProvider* CSVPSessionBase::ForwardProviderL( + const MCCPForwardObserver& /*aObserver*/ ) + { + return NULL; + } + + +// transfer observer + +// --------------------------------------------------------------------------- +// From MSVPTransferObserver +// Notifier for succesful transfer. +// --------------------------------------------------------------------------- +// +void CSVPSessionBase::TransferNotification( TInt aNotifyCode ) + { + SVPDEBUG2( "CSVPSessionBase::TransferNotification In, aNotifyCode: %d", + aNotifyCode ); + + if ( ESVPTransferOKHangUp == aNotifyCode ) + { + SVPDEBUG1( "CSVPSessionBase::TransferNotification: ESVPTransferOKHangUp" ) + // Transfer complete - hang up current session. + HangUp(); + } + else if ( ESVPTransferDecline == aNotifyCode ) + { + SVPDEBUG1( "CSVPSessionBase::TransferNotification: ESVPTransferDecline" ) + // Inform application - transfer was rejected by the other party, + // not a failure, to be precise + ExecCbErrorOccurred( ECCPTransferFailed ); + } + else if ( ESVPIncomingRefer == aNotifyCode ) + { + SVPDEBUG1( "CSVPSessionBase::TransferNotification: ESVPIncomingRefer" ) + // Currently no CallEventOccurred notify to the observer + } + else + { + // Internal transfer error if comes here + SVPDEBUG1( "CSVPSessionBase::TransferNotification: Unknown notify" ) + } + + SVPDEBUG1( "CSVPSessionBase::TransferNotification Out" ) + } + +// --------------------------------------------------------------------------- +// From MSVPTransferObserver +// Notifier for transfer failure. +// --------------------------------------------------------------------------- +// +#ifdef _DEBUG +void CSVPSessionBase::TransferFailed( TInt aError ) +#else +void CSVPSessionBase::TransferFailed( TInt /*aError*/ ) +#endif // _DEBUG + { + SVPDEBUG1( "CSVPSessionBase::TransferFailed In" ) + SVPDEBUG2(" CSVPSessionBase::TransferFailed aError=%d", aError ) + + // Inform application about the error + ExecCbErrorOccurred( ECCPTransferFailed ); + + SVPDEBUG1( "CSVPSessionBase::TransferFailed Out" ) + } + +// from CCP DTMF provider +// --------------------------------------------------------------------------- +// CSVPSessionBase::CancelDtmfStringSending +// --------------------------------------------------------------------------- +// +TInt CSVPSessionBase::CancelDtmfStringSending() + { + SVPDEBUG1( "CSVPSessionBase::CancelDtmfStringSending In" ) + + TInt dtmfErr( KErrNone ); + + if ( !iSVPUtility.GetDTMFMode() ) + { + dtmfErr = KErrNotFound; + if ( iEventGenerator ) + { + iEventGenerator->StopEvents(); + dtmfErr = KErrNone; + } + } + else + { + const RPointerArray& streams = iSession->Streams(); + TInt count = streams.Count(); + while( count ) + { + count--; + CMceMediaStream& mediaStream = *streams[ count ]; + if ( SVPAudioUtility::DtmfActionCapableStream( mediaStream ) ) + { + TRAP( dtmfErr, mediaStream.Source()->CancelDtmfToneSequenceL() ); + } + else + { + dtmfErr = KErrNotSupported; + } + + if ( KErrNone != dtmfErr ) + { + return dtmfErr; + } + } + } + + SVPDEBUG2( "CSVPSessionBase::CancelDtmfStringSending Out return=%d", dtmfErr ) + return dtmfErr; + } + +// --------------------------------------------------------------------------- +// CSVPSessionBase::StartDtmfTone +// --------------------------------------------------------------------------- +// +TInt CSVPSessionBase::StartDtmfTone( const TChar aTone ) + { + SVPDEBUG1( "CSVPSessionBase::StartDtmfTone In" ) + + TInt dtmfErr( KErrNone ); + + if ( iSVPUtility.GetDTMFMode() ) + { + SVPDEBUG1( "CSVPSessionBase::StartDtmfTone DTMF Outband" ) + // fetch streams + const RPointerArray& streams = iSession->Streams(); + TInt count = streams.Count(); + while ( count ) + { + count--; + CMceMediaStream& mediaStream = *streams[ count ]; + if ( SVPAudioUtility::DtmfActionCapableStream( mediaStream ) ) + { + TRAP( dtmfErr, mediaStream.Source()->StartDtmfToneL( aTone ) ); + } + else + { + dtmfErr = KErrNotSupported; + } + + if ( KErrNone != dtmfErr ) + { + SVPDEBUG2( "CSVPSessionBase::StartDtmfToneL dtmfErr: %d", + dtmfErr ) + + return dtmfErr; + } + } + } + else + { + SVPDEBUG1( "CSVPSessionBase::StartDtmfTone DTMF Inband" ) + iDtmfTone = aTone; + DtmfObserver().HandleDTMFEvent( MCCPDTMFObserver::ECCPDtmfManualStart, + KErrNone, + aTone ); + } + + SVPDEBUG2( "CSVPSessionBase::StartDtmfTone Out return=%d", dtmfErr ) + return dtmfErr; + } + +// --------------------------------------------------------------------------- +// CSVPSessionBase::StopDtmfTone +// --------------------------------------------------------------------------- +// +TInt CSVPSessionBase::StopDtmfTone() + { + SVPDEBUG1( "CSVPSessionBase::StopDtmfTone In" ) + + TInt dtmfErr( KErrNone ); + + if ( iSVPUtility.GetDTMFMode() ) + { + const RPointerArray& streams = iSession->Streams(); + TInt count = streams.Count(); + while( count ) + { + count--; + CMceMediaStream& mediaStream = *streams[ count ]; + if ( SVPAudioUtility::DtmfActionCapableStream( mediaStream ) ) + { + TRAP( dtmfErr, mediaStream.Source()->StopDtmfToneL() ); + } + // NOP with inband. + + if ( KErrNone != dtmfErr ) + { + SVPDEBUG2( "CSVPSessionBase::StopDtmfTone dtmfErr: %d", + dtmfErr ) + + return dtmfErr; + } + } + } + else + { + DtmfObserver().HandleDTMFEvent( MCCPDTMFObserver::ECCPDtmfManualStop, + KErrNone, + iDtmfTone ); + } + + SVPDEBUG2( "CSVPSessionBase::StopDtmfTone Out return=%d", dtmfErr ) + return dtmfErr; + } + +// --------------------------------------------------------------------------- +// CSVPSessionBase::SendDtmfToneString +// --------------------------------------------------------------------------- +// +TInt CSVPSessionBase::SendDtmfToneString( const TDesC& aString ) + { + SVPDEBUG1( "CSVPSessionBase::SendDtmfToneString In" ) + + TInt dtmfErr( KErrNone ); + TChar dtmfPause('p'); + // MCE calls if outband DTMF. + // Exception is pause character 'p' which is handled always locally + if ( !iSVPUtility.GetDTMFMode() || + ( aString.Length() == 1 && + dtmfPause == aString[0] ) ) + { + SVPDEBUG1( "CSVPSessionBase::SendDtmfToneString Inband" ) + + delete iDtmfString; + iDtmfString = NULL; + TRAP( dtmfErr, iDtmfString = HBufC::NewL( aString.Length() ) ); + if ( KErrNone != dtmfErr ) + { + return dtmfErr; + } + + *iDtmfString = aString; + iDtmfLex.Assign( *iDtmfString ); + + if ( !iEventGenerator ) + { + TRAP( dtmfErr, + iEventGenerator = CSVPDTMFEventGenerator::NewL( *this ) ); + } + + if ( KErrNone != dtmfErr ) + { + SVPDEBUG2( "CSVPSessionBase::SendDtmfToneString IB dtmfErr: %d", + dtmfErr ) + + return dtmfErr; + } + + // Dtmf pause length is 2500ms + TBool pauseChar = ( aString.Length() == 1 && + dtmfPause == aString[0] ); + // start events + iEventGenerator->StartDtmfEvents( aString.Length(), pauseChar ); + } + else + { + SVPDEBUG1( "CSVPSessionBase::SendDtmfToneString Outband" ) + + const RPointerArray& streams = iSession->Streams(); + TInt count = streams.Count(); + while( count ) + { + count--; + CMceMediaStream& mediaStream = *streams[ count ]; + + if ( SVPAudioUtility::DtmfActionCapableStream( mediaStream ) ) + { + TRAP( dtmfErr, + mediaStream.Source()->SendDtmfToneSequenceL( aString ) ); + } + else + { + dtmfErr = KErrNotSupported; + } + + if ( KErrNone != dtmfErr ) + { + SVPDEBUG2( "CSVPSessionBase::SendDtmfToneString Out OB dtmfErr: %d", dtmfErr ) + return dtmfErr; + } + } + } + + SVPDEBUG2( "CSVPSessionBase::SendDtmfToneString Out return=%d", dtmfErr ) + return dtmfErr; + } + + +// from MSVPPropertyWatchObserver +// --------------------------------------------------------------------------- +// CSVPSessionBase::ValueChangedL +// --------------------------------------------------------------------------- +// +void CSVPSessionBase::ValueChangedL( TInt aKey, TInt aValue ) + { + SVPDEBUG3("CSVPSessionBase::ValueChangedL In aKey: %d, aValue: %d ", aKey, aValue ) + + // fetch streams from session + const RPointerArray& streams = iSession->Streams(); + + switch ( aKey ) + { + case KTelMicrophoneMuteState: + { + PerformMuteChangeL( streams, aValue ); + break; + } + default: + { + SVPDEBUG1( "CSVPSessionBase::ValueChangedL DEFAULT - NOP" ) + break; + } + } + + SVPDEBUG1( "CSVPSessionBase::ValueChangedL Out" ) + } + +// --------------------------------------------------------------------------- +// CSVPSessionBase::PerformMuteChangeL +// --------------------------------------------------------------------------- +// +void CSVPSessionBase::PerformMuteChangeL( + const RPointerArray& aStreams, TInt aValue ) + { + SVPDEBUG1( "CSVPSessionBase::PerformMuteChangeL In" ) + + if ( CMceSession::EOffering == iSession->State() || + iHoldController && ESVPOnHold == iHoldController->HoldState() ) + { + // call is ringing or on hold, we don't perform mute or unmute + SVPDEBUG1( "CSVPSessionBase::PerformMuteChangeL, no need for mute nor unmute" ) + } + else + { + for ( TInt i = 0; i < aStreams.Count(); i++ ) + { + if ( IsMobileOriginated() ) + { + if ( aStreams[ i ]->Source() ) + { + if ( EPSTelMicMuteOn == aValue ) + { + // mute mic source + SVPAudioUtility::DisableMicSourceL( + *( aStreams[ i ]->Source() ) ); + } + else + { + // un-mute mic source + SVPAudioUtility::EnableMicSourceL( + *( aStreams[ i ]->Source() ) ); + } + } + } + else + { + if( CMceSession::EEstablished == iSession->State() ) + { + if ( EPSTelMicMuteOn == aValue ) + { + // mute mic source + SVPAudioUtility::DisableMicSourceL( + *( aStreams[ i ]->BoundStreamL().Source() ) ); + } + else + { + // un-mute mic source + SVPAudioUtility::EnableMicSourceL( + *( aStreams[ i ]->BoundStreamL().Source() ) ); + } + } + } + } + + if ( EPSTelMicMuteOff == aValue ) + { + SVPDEBUG1( "CSVPSessionBase::PerformMuteChangeL - Enable Speaker" ) + SVPAudioUtility::EnableSpeakerSinksL( aStreams ); + } + } + + if ( EPSTelMicMuteOn == aValue ) { iMuted = ETrue; } + if ( EPSTelMicMuteOff == aValue ) { iMuted = EFalse; } + + if ( iHoldController ) + { + SVPDEBUG1( "CSVPSessionBase::PerformMuteChangeL - update mute status" ) + iHoldController->Muted( iMuted ); + } + + SVPDEBUG1( "CSVPSessionBase::PerformMuteChangeL Out" ) + } + +// --------------------------------------------------------------------------- +// CSVPSessionBase::PropertyDeleted +// --------------------------------------------------------------------------- +// +#ifdef _DEBUG +void CSVPSessionBase::PropertyDeleted( TInt aKey ) +#else +void CSVPSessionBase::PropertyDeleted( TInt /*aKey*/ ) +#endif // __DEBUG + { + SVPDEBUG2("CSVPSessionBase::PropertyDeleted aKey=%d", aKey ) + } + + +// from MSVPVolumeUpdateObserver +// --------------------------------------------------------------------------- +// CSVPSessionBase::VolumeChanged +// --------------------------------------------------------------------------- +// +void CSVPSessionBase::VolumeChanged( TInt aVolume ) + { +#ifdef _DEBUG + TRAPD( volErr, VolumeChangedL( aVolume ) ); + SVPDEBUG2("CSVPSessionBase::VolumeChanged volErr=%d", volErr ) +#else + TRAP_IGNORE( VolumeChangedL( aVolume ) ) +#endif // _DEBUG + } + +// --------------------------------------------------------------------------- +// CSVPSessionBase::VolumeChangedL +// --------------------------------------------------------------------------- +// +void CSVPSessionBase::VolumeChangedL( TInt aVolume ) + { + SVPDEBUG1( "CSVPSessionBase::VolumeChangedL In" ) + + // fetch streams from session + const RPointerArray& stream = iSession->Streams(); + + for ( TInt i = 0; i < stream.Count(); i++ ) + { + // fetch mediastreams for handling + CMceMediaStream* mediaStream = stream[ i ]; + CMceMediaStream& boundStream = mediaStream->BoundStreamL(); + + // fetch sinks from current stream + const RPointerArray& sinks = mediaStream->Sinks(); + + for ( TInt y = 0; y < sinks.Count(); y++ ) + { + // find speaker sink + if ( KMceSpeakerSink == sinks[ y ]->Type() ) + { + SVPDEBUG1( "CSVPSessionBase::VolumeChangedL Speaker found(A)" ) + CMceSpeakerSink* speakerSink = + static_cast( sinks[ y ] ); + // get sink max volume and adjust setVol accordingly + TInt maxVol = speakerSink->MaxVolumeL(); + TInt setVol = maxVol * aVolume / KMaxPhoneVolume; + + SVPDEBUG2("CSVPSessionBase::VolumeChangedL maxVol=%d", maxVol ) + SVPDEBUG2("CSVPSessionBase::VolumeChangedL aVolume=%d", aVolume ) + SVPDEBUG2("CSVPSessionBase::VolumeChangedL setVol=%d", setVol ) + + speakerSink->SetVolumeL( setVol ); + } + } + + const RPointerArray& boundSinks = boundStream.Sinks(); + + for ( TInt z = 0; z < boundSinks.Count(); z++ ) + { + // find speaker sink from bound stream + if ( KMceSpeakerSink == boundSinks[ z ]->Type() ) + { + SVPDEBUG1( "CSVPSessionBase::VolumeChangedL Speaker found(B)" ) + + CMceSpeakerSink* speakerSink = + static_cast( boundSinks[ z ] ); + // get sink max volume and adjust setVol accordingly + TInt maxVol = speakerSink->MaxVolumeL(); + TInt setVol = maxVol * aVolume / KMaxPhoneVolume; + + SVPDEBUG2("CSVPSessionBase::VolumeChangedL maxVol=%d", maxVol ) + SVPDEBUG2("CSVPSessionBase::VolumeChangedL aVolume=%d", aVolume ) + SVPDEBUG2("CSVPSessionBase::VolumeChangedL setVol=%d", setVol ) + + speakerSink->SetVolumeL( setVol ); + } + } + } + + SVPDEBUG1( "CSVPSessionBase::VolumeChangedL Out" ) + } + +// --------------------------------------------------------------------------- +// CSVPSessionBase::SecureMandatory +// --------------------------------------------------------------------------- +// +TBool CSVPSessionBase::SecureMandatory() const + { + SVPDEBUG2( "CSVPSessionBase::SecureMandatory=%d", iSecureMandatory ) + return iSecureMandatory; + } + +// --------------------------------------------------------------------------- +// CSVPSessionBase::SecurePreferred +// --------------------------------------------------------------------------- +// +TBool CSVPSessionBase::SecurePreferred() const + { + SVPDEBUG2( "CSVPSessionBase::SecurePreferred=%d", iSecurePreferred ) + return iSecurePreferred; + } + +// --------------------------------------------------------------------------- +// CSVPSessionBase::SetSecureMandatory +// --------------------------------------------------------------------------- +// +void CSVPSessionBase::SetSecureMandatory( TBool aSecMandatory ) + { + iSecureMandatory = aSecMandatory; + } + +// --------------------------------------------------------------------------- +// CSVPSessionBase::SetSecurePreferred +// --------------------------------------------------------------------------- +// +void CSVPSessionBase::SetSecurePreferred( TBool aSecPreferred ) + { + iSecurePreferred = aSecPreferred; + } + +// --------------------------------------------------------------------------- +// CSVPSessionBase::SetCallEventToBeSent +// --------------------------------------------------------------------------- +// +void CSVPSessionBase::SetCallEventToBeSent( MCCPCallObserver::TCCPCallEvent aCallEventToBeSent ) + { + SVPDEBUG1( "CSVPSessionBase::SetCallEventToBeSent" ) + iCallEventToBeSent = aCallEventToBeSent; + } + +// --------------------------------------------------------------------------- +// CSVPSessionBase::SetParameters +// --------------------------------------------------------------------------- +// +void CSVPSessionBase::SetParameters( + const CCCPCallParameters& /*aNewParams*/ ) + { + SVPDEBUG1( "CSVPSessionBase::SetParameters - NOP" ) + } + +// --------------------------------------------------------------------------- +// CSVPSessionBase::Parameters +// --------------------------------------------------------------------------- +// +const CCCPCallParameters& CSVPSessionBase::Parameters() const + { + SVPDEBUG1( "CSVPSessionBase::Parameters In" ) + return *iCallParameters; + } + +// --------------------------------------------------------------------------- +// CSVPSessionBase::Tone +// --------------------------------------------------------------------------- +// +TCCPTone CSVPSessionBase::Tone() const + { + SVPDEBUG2( "CSVPSessionBase::Tone iTone: %d", iTone ) + return iTone; + } + +// --------------------------------------------------------------------------- +// CSVPSessionBase::SetCryptoContextL +// --------------------------------------------------------------------------- +// +void CSVPSessionBase::SetCryptoContextL() + { + SVPDEBUG1( "CSVPSessionBase::SetCryptoContextL In" ) + + if ( KMceSessionSecure == iSession->Type() ) + { + // get supported crypto contexts + if ( IsMobileOriginated() ) + { + SVPDEBUG1( "CSVPSessionBase::SetCryptoContextL Secure Mo" ) + + const RArray& cryptoContext = + static_cast ( iSession )-> + SupportedCryptoContextsL(); + SVPDEBUG2( "CSVPSessionBase::SetCryptoContextL Supported crypto context count=%d", + cryptoContext.Count() ) + + // set crypto contexts to session + static_cast ( iSession )-> + SetCryptoContextsL( cryptoContext ); + } + else + { + SVPDEBUG1( "CSVPSessionBase::SetCryptoContextL Secure Mt" ) + + const RArray& cryptoContext = + static_cast ( iSession )-> + SupportedCryptoContextsL(); + SVPDEBUG2( "CSVPSessionBase::SetCryptoContextL Supported crypto context count=%d", + cryptoContext.Count() ) + + // set crypto contexts to session + static_cast ( iSession )-> + SetCryptoContextsL( cryptoContext ); + } + } + + SVPDEBUG1( "CSVPSessionBase::SetCryptoContextL Out" ) + } + +// --------------------------------------------------------------------------- +// CSVPSessionBase::CheckMmfPrioritiesForDtmfL +// --------------------------------------------------------------------------- +// +void CSVPSessionBase::CheckMmfPrioritiesForDtmfL( + const RPointerArray& aAudioStreams ) const + { + SVPDEBUG1( "CSVPSessionBase::CheckMmfPrioritiesForDtmfL In" ) + + RPointerArray micsToEnable; + CleanupClosePushL( micsToEnable ); + const TInt streamCount( aAudioStreams.Count() ); + + SVPDEBUG2("CSVPSessionBase::CheckMmfPrioritiesForDtmfL streamCount: %d", + streamCount ) + + // First disable the mic before doing any priority updating. + for ( TInt s = 0; s < streamCount; s++ ) + { + CMceMediaSource* mic = aAudioStreams[s]->Source(); + + if ( mic && KMceMicSource == mic->Type() && mic->IsEnabled() ) + { + SVPDEBUG1( "CSVPSessionBase::CheckMmfPrioritiesForDtmfL disable mic 1" ) + mic->DisableL(); + micsToEnable.AppendL( mic ); + } + + // At this point we must have a bound stream, otherwise the session + // would be a bit incomplete. Thus can and should leave here if bound + // stream is not found. + mic = NULL; + mic = aAudioStreams[s]->BoundStreamL().Source(); + + if ( mic && KMceMicSource == mic->Type() && mic->IsEnabled() ) + { + SVPDEBUG1( "CSVPSessionBase::CheckMmfPrioritiesForDtmfL disable mic 2" ) + mic->DisableL(); + micsToEnable.AppendL( mic ); + } + + mic = NULL; + } + + // Set the correct priority and preference values. + for ( TInt k = 0; k < streamCount; k++ ) + { + // No need to check against BoundStream(), see comments above. + if ( KMceAudio == aAudioStreams[k]->Type() ) + { + SVPDEBUG2( "CSVPSessionBase::CheckMmfPrioritiesForDtmfL round: %d start", k ) + CMceAudioStream* stream = static_cast( aAudioStreams[k] ); + + TBool dtmfMode = EFalse; + + if ( SVPAudioUtility::IsDownlinkStream( *stream ) ) + { + dtmfMode = SVPAudioUtility::SetPriorityCodecValuesL( *stream, + static_cast( stream->BoundStreamL() ) ); + } + else + { + dtmfMode = SVPAudioUtility::SetPriorityCodecValuesL( + static_cast( stream->BoundStreamL() ), + *stream ); + } + + iSVPUtility.SetDtmfMode( dtmfMode ); + + SVPDEBUG2( "CSVPSessionBase::CheckMmfPrioritiesForDtmfL round: %d done", k ) + } + } + + // Priorities are now correct, so update the session. + iSession->UpdateL(); + + // Now enable mics after we have correct priorities. + const TInt mics = micsToEnable.Count(); + + for ( TInt t = 0; t < mics; t++ ) + { + SVPDEBUG2( "CSVPSessionBase::CheckMmfPrioritiesForDtmfL enabling mics, round: %d", t ) + micsToEnable[t]->EnableL(); + } + + // Mics not owned + CleanupStack::PopAndDestroy( &micsToEnable ); + + SVPDEBUG1( "CSVPSessionBase::CheckMmfPrioritiesForDtmfL Out" ) + } + +// --------------------------------------------------------------------------- +// CSVPSessionBase::SessionStateChangedL +// --------------------------------------------------------------------------- +// +void CSVPSessionBase::SessionStateChangedL( TInt aOrigStatus, + TCCPError aError, TInt aModStatus ) + { + SVPDEBUG1( "CSVPSessionBase::SessionStateChangedL In" ) + SVPDEBUG2( "CSVPSessionBase::SessionStateChangedL aOrigStatus=%d", + aOrigStatus ) + SVPDEBUG2( "CSVPSessionBase::SessionStateChangedL aError=%d", + aError ) + SVPDEBUG2( "CSVPSessionBase::SessionStateChangedL aModStatus=%d", + aModStatus ) + + // secure status was "secure call mandatory", only secure allowed + if ( KErrNone != aModStatus && SecureMandatory() ) + { + if ( KSVPNotAcceptableHereVal == aModStatus || + KSVPNotAcceptableVal == aModStatus || + KSVPPreconditionFailureVal == aModStatus || + KSVPMethodNotAllowedVal == aModStatus ) + { + SVPDEBUG1( "CSVPSessionBase::SessionStateChangedL - Secure session failed!" ) + // secure call failed due to recipients restrictions + User::LeaveIfError( ExecCbErrorOccurred( ECCPSecureCallFailed ) ); + } + else + { + // secure call failed with SIP error response + // inform application about the error response received + User::LeaveIfError( ExecCbErrorOccurred( aError ) ); + + // start termination timer, needed for UI + // to handle Disconnected-bubble + StartTimerL( KSVPTerminatingTime, KSVPTerminationTimerExpired ); + User::LeaveIfError( ExecCbCallStateChanged( MCCPCallObserver::ECCPStateDisconnecting ) ); + } + } + + if ( KSVPRingingVal == aOrigStatus ) + { + SVPDEBUG1( "CSVPSessionBase::SessionStateChangedL - 180 ringing received" ) + User::LeaveIfError( ExecCbCallStateChanged( MCCPCallObserver::ECCPStateConnecting ) ); + if ( iEarlyMediaOngoing ) + { + // early media event is sent again to avoid simultaneous early media and ringback tone + SVPDEBUG1( "CSVPSessionBase::SessionStateChangedL ringing ja earlymedia flag on" ) + ExecCbCallEventOccurred( MCCPCallObserver::ECCCSPEarlyMediaStarted ); + iEarlyMediaOngoing = EFalse; + } + } + + if ( KSVPQueuedVal == aOrigStatus ) + { + SVPDEBUG1( "CSVPSessionBase::SessionStateChangedL - 182 queued received" ) + User::LeaveIfError( ExecCbSsEventOccurred( MCCPSsObserver::ESsCallWaiting ) ); + } + + switch( iSession->State() ) + { + case CMceSession::EEstablished: + { + // stop mt drop out timer or mo invite timer + StopTimers(); + + // mute status must be checked again in Mt -> + // there might be one call already in mute state + TInt value( EPSTelMicMuteOff ); + RProperty::Get( KPSUidTelMicrophoneMuteStatus, + KTelMicrophoneMuteState, value ); + + // check initial mute status + if ( EPSTelMicMuteOn == value ) + { + SVPDEBUG1( "CSVPSessionBase::SessionStateChangedL Mute: ON" ) + ValueChangedL( KTelMicrophoneMuteState, EPSTelMicMuteOn ); + } + // secure session created successfully, set iSecured flag to ETrue + if ( KMceSessionSecure == iSession->Type() && + CMceSession::EControlPathSecure == iSession->ControlPathSecurityLevel() ) + { + SVPDEBUG1( "CSVPSessionBase::SessionStateChangedL - Secure session created" ) + iSecured = ETrue; + } + else + { + SVPDEBUG1( "CSVPSessionBase::SessionStateChangedL - Non-secure session created" ) + iSecured = EFalse; + if ( SecurePreferred() ) + { + // Secure preferred but unsecure session created -> send info to ccp api + SVPDEBUG1( "CSVPSessionBase::SessionStateChangedL - secure was preferred" ) + iCallEventToBeSent = MCCPCallObserver::ECCPNotSecureCall; + } + } + + // We need get the call state now because session state will + // change when doing CheckMmfPrioritiesForDtmfL because it updates + // the session. This leads into 'Offering' state which will + // panic our State() function call. + // Note: session's state will fall back to 'Established' because + // the priority update does not lead into a real update. + MCCPCallObserver::TCCPCallState callState = State(); + + // We need to check MMF priorities only in MO case if really + // neccessary + if ( IsMobileOriginated() && + SVPAudioUtility::MmfPriorityUpdateNeededL( iSession->Streams() ) ) + { + CheckMmfPrioritiesForDtmfL( iSession->Streams() ); + } + if ( IsMobileOriginated() ) + { + TBool sessionUpdateOngoing = EFalse; + UpdateKeepAliveL( *iSession, sessionUpdateOngoing ); + } + + // enable speaker sink + SVPAudioUtility::EnableSpeakerSinksL( iSession->Streams() ); + // call state callback + User::LeaveIfError( ExecCbCallStateChanged( callState ) ); + + // 'NotSecure' call event must be sent after the + // 'callstatechanged' - event, not before because phone needs an + // active call for playing the unsecure tone. + if ( MCCPCallObserver::ECCPSecureNotSpecified != iCallEventToBeSent ) + { + if ( MCCPCallObserver::ECCPSecureCall == iCallEventToBeSent || + MCCPCallObserver::ECCPNotSecureCall == iCallEventToBeSent ) + { + SVPDEBUG1( "CSVPSessionBase::SessionStateChangedL - sending secure specific call event" ) + User::LeaveIfError( ExecCbCallEventOccurred( iCallEventToBeSent ) ); + } + SVPDEBUG1( "CSVPSessionBase::SessionStateChangedL - sending remotePartyInfoChanged event" ) + User::LeaveIfError( ExecCbCallEventOccurred( MCCPCallObserver::ECCPNotifyRemotePartyInfoChange ) ); + iCallEventToBeSent = MCCPCallObserver::ECCPSecureNotSpecified; + } + break; + } + case CMceSession::EAnswering: + case CMceSession::EReserving: + case CMceSession::EIncoming: + case CMceSession::EOffering: + { + SVPDEBUG1( "CSVPSessionBase:SessionStateChangedL: No action" ) + break; + } + case CMceSession::ECancelling: + case CMceSession::EIdle: + case CMceSession::ETerminating: + case CMceSession::EProceeding: + { + SVPDEBUG1( "CSVPSessionBase:SessionStateChangedL: Callback state change" ) + User::LeaveIfError( ExecCbCallStateChanged( State() ) ); + break; + } + case CMceSession::ETerminated: + { + SVPDEBUG1( "CSVPSessionBase::SessionStateChangedL Terminated" ) + + if ( MCCPCallObserver::ECCPStateDisconnecting != iSessionState && + MCCPCallObserver::ECCPStateIdle != iSessionState && + iCCPSessionObserver ) + { + // probably some SIP error occurred, inform client + if ( aOrigStatus < 0 ) + { + SVPDEBUG2( "CSVPSessionBase::SessionStateChangedL, aOrigStatus=%d", aOrigStatus ) + + switch ( aOrigStatus ) + { + case KErrSIPForbidden: + { + User::LeaveIfError( ExecCbErrorOccurred( ECCPErrorNoService ) ); + } + break; + default: + { + User::LeaveIfError( ExecCbErrorOccurred( ECCPGlobalFailure ) ); + } + break; + } + } + + if ( KErrNone != aModStatus ) + { + User::LeaveIfError( ExecCbErrorOccurred( aError ) ); + } + + iSessionState = MCCPCallObserver::ECCPStateDisconnecting; + iTerminatingRepeat = 0; + + StartTimerL( KSVPTerminatingTime, KSVPTerminationTimerExpired ); + User::LeaveIfError( ExecCbCallStateChanged( State() ) ); + + // Termination engaged by the remote end -> + // Client is informed with ECCPRemoteTerminated event + // This prevents automatic unhold when two calls, + // one on hold and one active, exist. + if ( !iAlreadyTerminating ) + { + User::LeaveIfError( ExecCbCallEventOccurred( + MCCPCallObserver::ECCPRemoteTerminated ) ); + } + } + else if ( iCCPSessionObserver ) + { + User::LeaveIfError( ExecCbCallStateChanged( + MCCPCallObserver::ECCPStateIdle ) ); + } + else + { + SVPDEBUG1( "CSVPSessionBase::SessionStateChangedL Session creation failed in early stage - terminate" ) + iObserver.TerminateSession( (CMceInSession&) Session() ); + } + break; + } + default: + { + SVPDEBUG1( "CSVPSessionBase:SessionStateChangedL DEFAULT" ) + break; + } + } + + SVPDEBUG1( "CSVPSessionBase::SessionStateChangedL Out" ) + } + +// --------------------------------------------------------------------------- +// CSVPSessionBase::UpdateKeepAliveL +// --------------------------------------------------------------------------- +// +void CSVPSessionBase::UpdateKeepAliveL( CMceSession& aSession, + TBool aSessionUpdateOngoing ) + { + SVPDEBUG1( "CSVPSessionBase:UpdateKeepAliveL In" ) + + // update keepalive -> mo and mt + SVPDEBUG1( "CSVPSessionBase::UpdateKeepAliveL Starting CN handling" ) + + const RPointerArray& streamArray = aSession.Streams(); + TInt streamCount( streamArray.Count() ); + TBool cnInAnswer = EFalse; + + for ( TInt i = 0; i < streamCount; i++ ) + { + CMceAudioStream* stream = static_cast( streamArray[ i ] ); + + if ( iSVPUtility.IsComfortNoise( *stream ) ) + { + cnInAnswer = ETrue; + SVPDEBUG1( "CSVPSessionBase::UpdateKeepAliveL CN Found" ) + iSVPUtility.SetCNKeepAliveL( *stream, iKeepAliveValue ); + } + } + + if ( !cnInAnswer ) + { + SVPDEBUG1( "CSVPSessionBase::UpdateKeepAliveL CN NOT Found" ) + SVPDEBUG2( "CSVPSessionBase::SessionStateChangedL Streamcount: %d", streamCount ) + + while( streamCount-- ) + { + CMceAudioStream* stream = static_cast< CMceAudioStream* >( streamArray[ streamCount ] ); + iSVPUtility.SetKeepAliveL( *stream, iKeepAliveValue ); + } + } + + if ( !aSessionUpdateOngoing ) + { + SVPDEBUG1( "CSVPSessionBase::UpdateKeepAliveL -> UPDATE" ) + aSession.UpdateL(); + SVPDEBUG1( "CSVPSessionBase::UpdateKeepAliveL -> UPDATE DONE" ) + } + SVPDEBUG1("CSVPSessionBase:UpdateKeepAliveL Out") + } + +// --------------------------------------------------------------------------- +// CSVPSessionBase::UpdateFailed +// --------------------------------------------------------------------------- +// +void CSVPSessionBase::UpdateFailed( CMceSession& aSession, TInt aStatusCode ) + { + SVPDEBUG1( "CSVPSessionBase::UpdateFailed In" ) + SVPDEBUG2( "CSVPSessionBase::UpdateFailed aStatusCode=%d", aStatusCode ) + + // Check if MCE Session has changed + if ( &Session() != &aSession ) + { + // And if, then update to the current session + SVPDEBUG1( "CSVPSessionBase::UpdateFailed - update MCE Session" ) + delete iSession; + iSession = &aSession; + } + + if ( iHoldController ) + { + iHoldController->RequestFailed( aSession, aStatusCode, *this ); + } + + SVPDEBUG1( "CSVPSessionBase::UpdateFailed Out" ) + } + + +// --------------------------------------------------------------------------- +// CSVPSessionBase::SetRtpKeepAliveL +// --------------------------------------------------------------------------- +// +void CSVPSessionBase::SetRtpKeepAliveL( CMceSession* /*aSession*/, + TBool /*aSessionUpdateOngoing*/ ) + { + SVPDEBUG1( "CSVPSessionBase::SetRtpKeepAliveL" ) + } + +// --------------------------------------------------------------------------- +// CSVPSessionBase::SetUpdatedSession +// --------------------------------------------------------------------------- +// +void CSVPSessionBase::SetUpdatedSession( CMceInSession* aUpdatedSession ) + { + SVPDEBUG1( "CSVPSessionBase::SetUpdatedSession In" ) + + delete iSession; + iSession = aUpdatedSession; + + // lets check should mic be muted + const RPointerArray& streamsArray = iSession->Streams(); + const TInt streamCount( streamsArray.Count() ); + if ( streamCount && iMuted ) + { + SVPDEBUG1( "CSVPSessionBase::SetUpdatedSession Mic should be muted" ) + + if ( IsMobileOriginated() ) + { + for ( TInt i = 0; i < streamCount; i++ ) + { + if ( streamsArray[i]->Source()->IsEnabled() ) + { + SVPDEBUG1( "CSVPSessionBase::SetUpdatedSession Mic is not muted" ) + SVPDEBUG1( " -> disable mic" ) + streamsArray[i]->Source()->DisableL(); + } + else + { + SVPDEBUG1( "CSVPSessionBase::SetUpdatedSession Mic is already" ) + SVPDEBUG1( " muted -> no need to disable mic" ) + } + } + } + else + { + // mute mic source + for ( TInt i = 0; i < streamCount; i++ ) + { + if ( streamsArray[i]->BoundStreamL().Source()->IsEnabled() ) + { + streamsArray[i]->BoundStreamL().Source()->DisableL(); + } + } + } + } + + // Update changed session also to the transfercontroller + if ( iTransferController ) + { + SVPDEBUG1( "CSVPSessionBase::SetUpdatedSession also to the transfercontroller" ) + iTransferController->SetMceSessionObject( aUpdatedSession ); + } + + SVPDEBUG1( "CSVPSessionBase::SetUpdatedSession Out" ) + } + +// --------------------------------------------------------------------------- +// CSVPSessionBase::SetEmptyReInvite +// --------------------------------------------------------------------------- +// +void CSVPSessionBase::SetEmptyReInvite() + { + SVPDEBUG1( "CSVPSessionBase::SetEmptyReInvite In" ) + iEmptyReInvite = ETrue; + } + +// --------------------------------------------------------------------------- +// CSVPSessionBase::IsEmptyReInvite +// --------------------------------------------------------------------------- +// +TBool CSVPSessionBase::IsEmptyReInvite() + { + SVPDEBUG1( "CSVPSessionBase::IsEmptyReInvite In" ) + return iEmptyReInvite; + } + +// --------------------------------------------------------------------------- +// CSVPSessionBase::IsIdle +// --------------------------------------------------------------------------- +// +TBool CSVPSessionBase::IsIdle() + { + SVPDEBUG1( "CSVPSessionBase::IsIdle In" ) + return ( MCCPCallObserver::ECCPStateIdle == iSessionState ); + } + +// --------------------------------------------------------------------------- +// CSVPSessionBase::SecureSpecified +// --------------------------------------------------------------------------- +// +TBool CSVPSessionBase::SecureSpecified( ) const + { + return ETrue; + } + +// --------------------------------------------------------------------------- +// CSVPSessionBase::SetErrorInULandDLFirstTime +// --------------------------------------------------------------------------- +// +void CSVPSessionBase::SetErrorInULandDLFirstTime( TBool aFirstTime ) + { + iErrorInULandDLFirstTime = aFirstTime; + SVPDEBUG2("CSVPSessionBase::SetErrorInULandDLFirstTime=%d",iErrorInULandDLFirstTime) + } + +// --------------------------------------------------------------------------- +// CSVPSessionBase::IsErrorInULandDLFirstTime +// --------------------------------------------------------------------------- +// +TBool CSVPSessionBase::IsErrorInULandDLFirstTime() + { + SVPDEBUG2("CSVPSessionBase::IsErrorInULandDLFirstTime=%d",iErrorInULandDLFirstTime) + return iErrorInULandDLFirstTime; + } + + +// --------------------------------------------------------------------------- +// CSVPSessionBase::IsBothStreamsDisabledL +// --------------------------------------------------------------------------- +// +TBool CSVPSessionBase::IsBothStreamsDisabledL() const + { + SVPDEBUG1( "CSVPSessionBase::IsBothStreamsDisabledL() In" ) + TBool bothStreamsDisabled = ETrue; + const RPointerArray& streams = Session().Streams(); + TInt streamsCount = streams.Count(); + + for ( TInt i = 0; i < streamsCount; i++ ) + { + if( streams[ i ]->State() != CMceMediaStream::EDisabled || + streams[ i ]->BoundStreamL().State() != CMceMediaStream::EDisabled ) + { + bothStreamsDisabled = EFalse; + } + } + + SVPDEBUG2("CSVPSessionBase::IsBothStreamsDisabledL Out,ret=%d",bothStreamsDisabled) + return bothStreamsDisabled; + } + +// --------------------------------------------------------------------------- +// CSVPSessionBase::IsSessionMuted +// --------------------------------------------------------------------------- +// +TBool CSVPSessionBase::IsSessionMuted() const + { + SVPDEBUG2("CSVPSessionBase::IsSessionMuted: %d", iMuted ) + return iMuted; + } + +// --------------------------------------------------------------------------- +// CSVPSessionBase::IsCLIROnL +// --------------------------------------------------------------------------- +// +TBool CSVPSessionBase::IsCLIROnL() const + { + return iSVPUtility.IsCLIROnL(); + }