diff -r 000000000000 -r ff3b6d0fd310 convergedcallengine/cce/src/cccecallcontainer.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/convergedcallengine/cce/src/cccecallcontainer.cpp Tue Feb 02 01:11:09 2010 +0200 @@ -0,0 +1,1369 @@ +/* +* Copyright (c) 2006-2008 Nokia Corporation and/or its subsidiary(-ies). +* All rights reserved. +* This component and the accompanying materials are made available +* under the terms of "Eclipse Public License v1.0" +* which accompanies this distribution, and is available +* at the URL "http://www.eclipse.org/legal/epl-v10.html". +* +* Initial Contributors: +* Nokia Corporation - initial contribution. +* +* Contributors: +* +* Description: class of call objects +* +*/ + + +// INCLUDE FILES +#include "cccecallcontainer.h" +#include "mccpcall.h" +#include "mccpcscall.h" +#include "mcceobserver.h" +#include "mccessobserver.h" +#include "cccecall.h" +#include "cccelogger.h" +#include "ccceutility.h" +#include "ccceconferencecall.h" +#include "ccceemergencycall.h" +#include "cccedtmf.h" +#include "cccetransfercontroller.h" +#include "cconvergedcallprovider.h" +#include "ccceextension.h" +#include "cccepluginmanager.h" +#include "cccedurationtimer.h" +#include "cccecallinfomediator.h" + +#include + +//CONSTANTS +const TInt KCSServiceId = 1; + +// ======== MEMBER FUNCTIONS ======== +// --------------------------------------------------------------------------- +// Constructor +// --------------------------------------------------------------------------- +// +CCCECallContainer::CCCECallContainer( MCCEObserver& aObserver ): iMCCEObserver(&aObserver) + { + // Initialize callinfo call ids + for ( TInt i = 0; i < KCCECallObjects; i++ ) + { + iCallInfoCallId[ i ] = KErrNotFound; + } + + } + +// --------------------------------------------------------------------------- +// Construct object +// --------------------------------------------------------------------------- +// +void CCCECallContainer::ConstructL() + { + FeatureManager::InitializeLibL(); + iCallStateMediator = CCCECallInfoMediator::NewL( *this ); + + CreateCallDataArraysL(); + + iTransferController = CCCETransferController::NewL( *this ); + iPluginManager = CCCEPluginManager::NewL( *this, *iTransferController ); + iEmergencyCall = CCCEEmergencyCall::NewL(*this, *iPluginManager); + iPluginManager->SetEmergencyCallObserver(*iEmergencyCall); + iExtension = CCCEExtension::NewL(*iPluginManager ); + iConferenceCall = CCCEConferenceCall::NewL( *this, *iPluginManager ); + if( iMCCEObserver ) + { + iPluginManager->SetObserver(*iMCCEObserver); + } + + // AirTime Timer + iCSDuration = CCCEDurationTimer::NewL(); + iPSDuration = CCCEDurationTimer::NewL(); + + iIdle = CIdle::NewL( CActive::EPriorityIdle ); + } + +// --------------------------------------------------------------------------- +// Default Symbian constructor +// --------------------------------------------------------------------------- +// +CCCECallContainer* CCCECallContainer::NewL( MCCEObserver& aObserver ) + { + CCCECallContainer* self = new( ELeave ) CCCECallContainer(aObserver); + CleanupStack::PushL( self ); + self->ConstructL(); + CleanupStack::Pop( self ); + return self; + } + +// --------------------------------------------------------------------------- +// Destructor +// --------------------------------------------------------------------------- +// +CCCECallContainer::~CCCECallContainer() + { + delete iConferenceCall; + delete iEmergencyCall; + delete iDtmf; + delete iExtension; + delete iPluginManager; + delete iTransferController; + + if( iCallArray ) + { + iCallArray->ResetAndDestroy(); + delete iCallArray; + } + + delete iCallStateMediator; + + iCallstoRelease.Reset(); + iCallstoRelease.Close(); + + delete iCSDuration; + delete iPSDuration; + + + if( iIdle ) + { + iIdle->Cancel(); + delete iIdle; + } + FeatureManager::UnInitializeLib(); + } +// ----------------------------------------------------------------------------- +// SetObserver() +// ----------------------------------------------------------------------------- +// +void CCCECallContainer::SetObserver( MCCEObserver& aObserver, MCCESsObserver& aSsObserver ) + { + iMCCEObserver = &aObserver; + iMCCESsObserver = &aSsObserver; + iPluginManager->SetObserver(aObserver ); + } + +// ----------------------------------------------------------------------------- +// Create call objects +// CS objects are located in the beginning of array and VoIP objects after those +// ----------------------------------------------------------------------------- +// +void CCCECallContainer::CreateCallDataArraysL() + { + CCCECall* call = NULL; + TInt callIndex = 0; + + iCallArray = new ( ELeave ) CArrayPtrFlat( KCCECallObjects ); + + for( callIndex = 0; callIndex < KCCECallObjects; callIndex++ ) + { + call = CCCECall::NewLC( *this, callIndex ); + iCallArray->AppendL( call ); + CleanupStack::Pop( call ); + } + } + +// ----------------------------------------------------------------------------- +// Swap PS and CS air duration timers +// Is called after handover, when call type has changed +// ----------------------------------------------------------------------------- +// +void CCCECallContainer::AirTimeDurationSwap( + const CCPCall::TCallType aNewCallType) + { + CCELOGSTRING("CCCECallContainer::AirTimeDurationSwap(): IN"); + + CCCECall* call = NULL; + TInt calls(0); + for ( TInt i = 0; i < KCCECallObjects; i++ ) + { + call = GetCall( i ); + if ( call->State() == CCPCall::EStateConnected || + call->State() == CCPCall::EStateHold ) + { + calls ++; + } + } + + if( CCPCall::EStateConnected == iEmergencyCall->State() ) + { + calls ++; + } + + if( 1 == calls ) + { + // After handover we will have only one active call + // If we have more or less, timer swapping will not happend + if (aNewCallType == CCPCall::ECallTypePS ) + { + CCELOGSTRING2("CCCECallContainer::AirTimeDurationSwap(): CS Stops, PS restarts from %d", + iCSDuration->NumberOfBeats() ); + iCSDuration->Stop(); + iPSDuration->RestartAirTimeDuration(iCSDuration->NumberOfBeats()); + iCSDuration->Reset(); + } + else + { + CCELOGSTRING2("CCCECallContainer::AirTimeDurationSwap(): PS Stops, CS restarts from %d", + iPSDuration->NumberOfBeats() ); + iPSDuration->Stop(); + iCSDuration->RestartAirTimeDuration(iPSDuration->NumberOfBeats()); + iPSDuration->Reset(); + } + } + CCELOGSTRING("CCCECallContainer::AirTimeDurationSwap(): OUT"); + } + +// --------------------------------------------------------------------------- +// AirTimeDurationStop() +// --------------------------------------------------------------------------- +// +void CCCECallContainer::AirTimeDurationStop( CCCECall* /*aCall*/ ) const + { + CCELOGSTRING("CCCECallContainer::AirTimeDurationStop(): IN"); + CCCECall* call = NULL; + TInt csCalls=0; + TInt psCalls=0; + + // Check if any other calls + for ( TInt i = 0; i < KCCECallObjects; i++ ) + { + call = GetCall( i ); + if ( call->State() == CCPCall::EStateConnected || + call->State() == CCPCall::EStateHold ) + { + if ( IsCsPlugin( call, EFalse ) ) + { + csCalls++; + CCELOGSTRING2(" AirTimeDurationStop() csCalls=%d ", csCalls); + } + // ps call found + else + { + psCalls++; + CCELOGSTRING2(" AirTimeDurationStop() psCalls=%d ", psCalls); + } + } + } + + if( CCPCall::EStateConnected == iEmergencyCall->State() ) + { + if( CCPCall::ECallTypePS == iEmergencyCall->Parameters().CallType() ) + { + psCalls++; + } + else + { + csCalls++; + } + } + + + // No other cs calls found + if( !csCalls ) + { + CCELOGSTRING(" AirTimeDurationStop() stop CS timer"); + iCSDuration->Stop(); + } + + // No other ps calls found + if( !psCalls ) + { + CCELOGSTRING(" AirTimeDurationStop() stop PS timer"); + iPSDuration->Stop(); + } + + + CCELOGSTRING("CCCECallContainer::AirTimeDurationStop(): IN"); + } + +// --------------------------------------------------------------------------- +// AirTimeDurationStart() +// --------------------------------------------------------------------------- +// +void CCCECallContainer::AirTimeDurationStart( CCCECall* /*aCall*/ ) const + { + CCELOGSTRING("CCCECallContainer::AirTimeDurationStart(): IN"); + CCCECall* call = NULL; + TInt csCalls=0; + TInt psCalls=0; + + // Check if any other calls + for ( TInt i = 0; i < KCCECallObjects; i++ ) + { + call = GetCall( i ); + if ( call->State() == CCPCall::EStateConnected || + call->State() == CCPCall::EStateHold ) + { + if ( IsCsPlugin( call, EFalse ) ) + { + csCalls++; + CCELOGSTRING2(" AirTimeDurationStart() csCalls=%d ", csCalls); + } + // ps call found + else + { + psCalls++; + CCELOGSTRING2(" AirTimeDurationStart() pscalls=%d ", psCalls); + } + } + } + + if( CCPCall::EStateConnected == iEmergencyCall->State() ) + { + if( CCPCall::ECallTypePS == iEmergencyCall->Parameters().CallType() ) + { + psCalls++; + } + else + { + csCalls++; + } + } + + // No other cs calls found + if( csCalls ) + { + iCSDuration->StartAirTimeDuration(); + } + // No other ps calls found + if( psCalls ) + { + iPSDuration->StartAirTimeDuration(); + } + CCELOGSTRING("CCCECallContainer::AirTimeDurationStart(): OUT"); + } + +// --------------------------------------------------------------------------- +// From base class MCCECallArray +// --------------------------------------------------------------------------- +// +MCCECallInfo* CCCECallContainer::EmergencyCallInfo() const + { + return iEmergencyCall; + } + +// --------------------------------------------------------------------------- +// From base class MCCECallArray +// --------------------------------------------------------------------------- +// +MCCECallInfo* CCCECallContainer::CallInfo( TInt aIndex ) const + { + return iCallArray->At( aIndex ); + } + +// --------------------------------------------------------------------------- +// From base class MCCECallArray +// --------------------------------------------------------------------------- +// +TInt CCCECallContainer::MaxNumberOfCalls() const + { + return iCallArray->Count(); + } + +// --------------------------------------------------------------------------- +// Add calls to be removed, and start releasing if not already running +// --------------------------------------------------------------------------- +// +void CCCECallContainer::ScheduleReleaseCall( MCCPCall& aCalltoRemove, const TUid aUid ) + { + TCallReleaseEntry entry; + entry.iCallToRelease = &aCalltoRemove; + entry.iUid = aUid; + iCallstoRelease.Append(entry); + if (!iIdle->IsActive()) + { + iIdle->Start( TCallBack(ReleaseCalls,this) ); + } + } + +// --------------------------------------------------------------------------- +// Callback to CIdle class to actually release calls +// --------------------------------------------------------------------------- +// +TInt CCCECallContainer::ReleaseCalls( TAny* aCallContainer ) + { + CCCECallContainer* container = + static_cast< CCCECallContainer* >( aCallContainer ); + container->DoReleaseCalls(); + + return KErrNone; + } + +// --------------------------------------------------------------------------- +// Callback to CIdle class to actually release calls +// --------------------------------------------------------------------------- +// +void CCCECallContainer::DoReleaseCalls() + { + CCELOGSTRING("CCCECallContainer::DoReleaseCalls()") + while( iCallstoRelease.Count() > 0 ) + { + CConvergedCallProvider* plugin = NULL; + TUid pluginUid = iCallstoRelease[0].iUid; + TRAP_IGNORE( plugin = iPluginManager->GetPluginL( pluginUid ) ); + if( plugin ) + { + // release call + plugin->ReleaseCall( *iCallstoRelease[0].iCallToRelease ); + + // first check can we indicate plugin release + if( !iEmergencyCall->IsInProgress() && + iPluginManager->ReleaseWhenIdle( pluginUid ) && + pluginUid != iConferenceCall->ImplementationUid() ) + { + // 2nd step + if( 0 == CountCalls( pluginUid ) ) + { + TBool releasePlugin = ETrue; + // and last test + if( 1 < iCallstoRelease.Count() ) + { + for( TInt a = 1; a < iCallstoRelease.Count(); a++ ) + { + if( iCallstoRelease[a].iUid == pluginUid ) + { + releasePlugin = EFalse; + } + } + } + + if( releasePlugin ) + { + iPluginManager->RemovePlugin( pluginUid ); + } + } + } + } + iCallstoRelease.Remove(0); + } + + }; + +// --------------------------------------------------------------------------- +// ConferenceCallL() +// --------------------------------------------------------------------------- +// +CCCEConferenceCall& CCCECallContainer::ConferenceCallL( + const MCCEConferenceCallObserver& aObserver ) + { + if( iConferenceCall ) + { + iConferenceCall->SetObserver( + const_cast( aObserver ) ); + } + else + { + iConferenceCall = CCCEConferenceCall::NewL( *this, *iPluginManager ); + iConferenceCall->SetObserver( + const_cast( aObserver ) ); + } + return *iConferenceCall; + } + +// --------------------------------------------------------------------------- +// ConferenceCall() +// --------------------------------------------------------------------------- +// +CCCEConferenceCall& CCCECallContainer::ConferenceCall() const + { + return *iConferenceCall; + } + +// --------------------------------------------------------------------------- +// DtmfInterfaceL() +// --------------------------------------------------------------------------- +// +CCCEDtmf& CCCECallContainer::DtmfInterfaceL( + const MCCEDtmfObserver& aObserver ) + { + if( iDtmf ) + { + iDtmf->SetObserver( aObserver ); + } + else + { + iDtmf = CCCEDtmf::NewL( *this, *iPluginManager ); + iDtmf->AddObserverL( aObserver ); + } + return *iDtmf; + } + +// --------------------------------------------------------------------------- +// ExtensionInterfaceL() +// --------------------------------------------------------------------------- +// + +MCCEExtensionInterface& CCCECallContainer::ExtensionInterfaceL( + const MCCEExtensionObserver& aObserver ) + { + if( iExtension ) + { + iExtension->AddObserverL( aObserver ); + } + else + { + iExtension = CCCEExtension::NewL(*iPluginManager ); + iExtension->AddObserverL( aObserver ); + } + return *iExtension; + } + +// --------------------------------------------------------------------------- +// GetNextFreeCall() +// --------------------------------------------------------------------------- +// +CCCECall* CCCECallContainer::GetNextFreeCall() const + { + CCCECall* call = NULL; + if ( !iEmergencyCall->IsInProgress()) + { + for (TInt i = 0; i < KCCECallObjects; i++ ) + { + call = GetCall( i ); + + if ( !call->IsInUse() ) + { + CCELOGSTRING("CCCE::GetNextFreeCall: Call found"); + break; + } + } + } + + return call; + } + +// --------------------------------------------------------------------------- +// GetCall() +// --------------------------------------------------------------------------- +// +CCCECall* CCCECallContainer::GetCall( CCPCall::TCallState aCallState, + CCCECall* aSkippedCall ) const + { + CCCECall* call = NULL; + CCPCall::TCallState callState = CCPCall::EStateIdle; + + for (TInt i = 0; i < KCCECallObjects; i++ ) + { + call = GetCall( i ); + + // Skip given call + if ( call == aSkippedCall ) + { + continue; + } + + + callState = call->State(); + if ( callState == aCallState ) + { + return call; + } + + } + + return NULL; + } + +// ----------------------------------------------------------------------------- +// Open new MCCP call and bind it to MCCECall +// ----------------------------------------------------------------------------- +// + MCCECall& CCCECallContainer::OpenNewCallL( + const TDesC& aNumber, + const CCCECallParameters& aCallParameters, + const MCCECallObserver& aCallObserver ) + { + CCCECall* call = GetNextFreeCall(); + + if(call) + { + CleanupReleasePushL( *call ); + + MCCPCall* convergedCall = NULL; + // This block could be put to own method in transfercontroller + if( iTransferController->TransferCall() && + CCCETransferController::ECCETypeUnattended == + iTransferController->OngoingTransferType() && + aNumber == iTransferController->TransferCall()->RemoteParty() ) + { + CCELOGSTRING("CCCE::OpenNewCallL: Use transfer call"); + convergedCall = iTransferController->TransferCall(); + // For MO transfer call observer needs to be set + convergedCall->AddObserverL( *call ); + call->SetTransferController( iTransferController ); + + convergedCall->SetParameters( aCallParameters ); + } + else + { + CCELOGSTRING2("CCCE::OpenNewCallL: ServiceId = %d", aCallParameters.ServiceId() ); + CConvergedCallProvider* plugin = + iPluginManager->GetPluginL( aCallParameters.ServiceId() ); + convergedCall = plugin->NewCallL(aCallParameters, aNumber, *call); + } + + if(convergedCall) + { + CCELOGSTRING("CCCE::OpenNewCallL: Set converged call to engine call"); + call->SetConvergedCallL( convergedCall, convergedCall->Uid() ); + call->SetObserver( aCallObserver ); + + CCELOGSTRING("CCCE::OpenNewCallL():OUT"); + } + else + { + CCELOGSTRING("CCCE::OpenNewCallL():No converged call:OUT"); + User::Leave( KErrGeneral ); + } + CleanupStack::Pop( call ); + } + else + { + CCELOGSTRING("CCCE::OpenNewCallL():No call:OUT"); + User::Leave( KErrGeneral ); + } + + return *call; + } +// ----------------------------------------------------------------------------- +// ReleaseCall +// ----------------------------------------------------------------------------- +// +TInt CCCECallContainer::ReleaseCall( MCCPCall& aCalltoRelease, const TUid aUid ) + { + + CCELOGSTRING("CCCECallContainer::ReleaseCall( MCCPCall& aCalltoRemove, const TUid aUid )"); + ScheduleReleaseCall(aCalltoRelease,aUid); + return KErrNone; + } + +// ----------------------------------------------------------------------------- +// ReleaseCall +// ----------------------------------------------------------------------------- +// +TInt CCCECallContainer::ReleaseCall( MCCPCall& aCalltoRelease) + { + CCELOGSTRING("CCCECallContainer::ReleaseCall( MCCPCall& aCalltoRelease )"); + TUid pluginUid = aCalltoRelease.Uid(); + return ReleaseCall(aCalltoRelease, pluginUid); + } + +// ----------------------------------------------------------------------------- +// Get emergencycall +// ----------------------------------------------------------------------------- +// + MCCECall& CCCECallContainer::EmergencyCall( const MCCECallObserver& aCallObserver ) + { + iEmergencyCall->SetObserver(aCallObserver); + return *iEmergencyCall; + } + +// ----------------------------------------------------------------------------- +// Get call object by call MCCPCall +// ----------------------------------------------------------------------------- +// +CCCECall* CCCECallContainer::GetCall( const MCCPCall* aMCCPCall ) const + { + CCCECall* call = NULL; + + for( TInt i = 0; i < iCallArray->Count(); i++ ) + { + call = iCallArray->At(i); + + if( aMCCPCall == &call->GetCCPCall() ) + { + CCELOGSTRING("CCCECallContainer::GetCall: Call found"); + break; + } + + call = NULL; + } + + return call; + } + +// --------------------------------------------------------------------------- +// GetCall() +// --------------------------------------------------------------------------- +// +TInt CCCECallContainer::GetCall( TUid aImplementationUid, + RPointerArray& aCallArray ) const + { + CCCECall* call = NULL; + + for ( TInt i = 0; i < KCCECallObjects; i++ ) + { + call = GetCall( i ); + if ( call->IsInUse() ) + { + if( call->ImplementationUid() == aImplementationUid ) + { + aCallArray.Append(call); + } + } + } + + return aCallArray.Count(); + } + +// --------------------------------------------------------------------------- +// IsAnyActiveOrConnectingCall() +// --------------------------------------------------------------------------- +// +TInt CCCECallContainer::GetActiveOrConnectingCalls( + RPointerArray& aCallArray ) const + { + CCPCall::TCallState callState = CCPCall::EStateIdle; + CCCECall* call = NULL; + TInt err = KErrNotFound; + TInt i = 0; + + for ( i = 0; i < KCCECallObjects; i++ ) + { + call = GetCall( i ); + if ( call->IsInUse() ) + { + callState = call->State(); + if ( callState == CCPCall::EStateDialling || + callState == CCPCall::EStateConnecting || + callState == CCPCall::EStateConnected ) + { + aCallArray.Append( call ); + err = KErrNone; + } + } + } + + if( iEmergencyCall->IsInProgress() ) + { + callState = iEmergencyCall->State(); + if ( callState == CCPCall::EStateDialling || + callState == CCPCall::EStateConnecting || + callState == CCPCall::EStateConnected ) + { + aCallArray.Append( iEmergencyCall ); + err = KErrNone; + } + } + + return err; + } + +// --------------------------------------------------------------------------- +// IsAnyActiveOrConnectingCall() +// --------------------------------------------------------------------------- +// +TInt CCCECallContainer::CountCalls( TUid aImplementationUid ) const + { + CCCECall* call = NULL; + TInt i = 0; + TInt count=0; + + for ( i = 0; i < KCCECallObjects; i++ ) + { + call = GetCall( i ); + if ( call->IsInUse() ) + { + if( call->ImplementationUid() == aImplementationUid ) + { + count++; + } + } + } + + if( iEmergencyCall->IsInProgress() ) + { + if( iEmergencyCall->ImplementationUid() == aImplementationUid ) + { + count++; + } + } + + return count; + } + +// --------------------------------------------------------------------------- +// CountCsCalls() +// --------------------------------------------------------------------------- +// +TInt CCCECallContainer::CountCsCalls( TUid aImplementationUid ) const + { + TInt count=0; + CCCECall* call = NULL; + TInt i = 0; + + for ( i = 0; i < KCCECallObjects; i++ ) + { + call = GetCall( i ); + if ( call->IsInUse() ) + { + if( call->ImplementationUid() == aImplementationUid && + ( call->Parameters().CallType() != CCPCall::ECallTypePS ) ) + { + count++; + } + } + } + + return count; + } + +// --------------------------------------------------------------------------- +// GetCallWithActiveRequest() +// --------------------------------------------------------------------------- +// +CCCECall* CCCECallContainer::GetCallWithActiveRequest( CCCECall* aCall ) const + { + CCCECall* call = NULL; + for( TInt i = 0; i < iCallArray->Count(); i++ ) + { + + if( CCCECall::ECCENone != iCallArray->At(i)->Request() ) + { + CCELOGSTRING( "CCCECallContainer::GetCallWithRequest: Call found" ); + if( iCallArray->At(i) != aCall ) + { + call = iCallArray->At(i); + } + } + } + + return call; + } + +// --------------------------------------------------------------------------- +// GetNonConferenceCall() +// --------------------------------------------------------------------------- +// +CCCECall* CCCECallContainer::GetNonConferenceCall() const + { + CCCECall* call = NULL; + for( TInt i = 0; i < iCallArray->Count(); i++ ) + { + if( iCallArray->At(i)->IsInUse() ) + { + if( !iConferenceCall->IsPartOfConference( *iCallArray->At(i) ) ) + { + CCELOGSTRING( "CCCECallContainer::GetNonConferenceCall: Call found" ); + call = iCallArray->At(i); + break; + } + } + } + + return call; + } + +// ----------------------------------------------------------------------------- +// Handle Conference status changes. +// If dial was pending for hold and hold is received, continue dial. +// ----------------------------------------------------------------------------- +// + +void CCCECallContainer::HandleConferenceStatusChange( + MCCEConferenceCallObserver::TCCEConferenceCallState aStatus ) + { + + CCELOGSTRING2("CCCECallContainer::HandleConferenceStatusChange: %d", aStatus ); + CCCECall* callWithRequest = GetCallWithActiveRequest( NULL ); + + switch ( aStatus ) + { + case MCCEConferenceCallObserver::ECCEConferenceIdle: + if ( callWithRequest && + callWithRequest->Request() == CCCECall::ECCEReplaceActive && + !GetCall( CCPCall::EStateConnected, callWithRequest ) ) + { + callWithRequest->DoPendingRequest(); + } + break; + + case MCCEConferenceCallObserver::ECCEConferenceHold: + if( iConferenceCall->EnumerateCalls() != 0 ) + { + // Swap 1/2 point ( two calls in hold ) if there isnt connected call allready + CCCECall* call = GetNonConferenceCall(); + if( call && + call->State() == CCPCall::EStateHold ) + { + if( call->ImplementationUid() == KCSProviderUid && + iConferenceCall->ImplementationUid() == KCSProviderUid ) + { + // If there is two cs calls do nothing + } + else + { + call->ResumeNoNotify(); + } + + break; + } + + // Answer new call when one(ringing) ongoing + // Answer new call when one(queued) ongoing + // Dial new call when one ongoing + if( callWithRequest ) + { + callWithRequest->DoPendingRequest(); + } + } + break; + case MCCEConferenceCallObserver::ECCEConferenceActive: + + // Swap completed + if( callWithRequest ) + { + callWithRequest->RequestComplete( ECCPErrorNone ); + } + default: + break; + + } + } + +// ----------------------------------------------------------------------------- +// Updates the call information API clients. +// ----------------------------------------------------------------------------- +// +void CCCECallContainer::HandleEmergencyCallStatusChange( + CCECallEnums::TNotifyType aNotify ) + { + CCELOGSTRING("CCCECallContainer::HandleEmergencyCallStatusChange(): IN"); + if ( aNotify != CCECallEnums::ENoNotify ) + { + iCallStateMediator->UpdateCallInfos(); + } + CCELOGSTRING("CCCECallContainer::HandleEmergencyCallStatusChange(): OUT"); + } + +// ----------------------------------------------------------------------------- +// Handle call status changes. +// If dial was pending for hold and hold is received, continue dial. +// If swap is active, and hold was received for wanted object, start resume other call +// If swap is active, and resume was received for wanted call, complete swap request +// ----------------------------------------------------------------------------- +// +void CCCECallContainer::HandleCallStatusChange( + CCPCall::TCallState aState, + CCCECall* aCall, + CCECallEnums::TNotifyType aNotify ) + { + CCELOGSTRING( "CCCECallContainer::HandleCallStatusChange(): IN" ); + CCCECall* call = NULL; + TInt error = KErrNone; + CCCECall* callWithRequest = GetCallWithActiveRequest( aCall ); + + switch ( aState ) + { + case CCPCall::EStateConnected: + AirTimeDurationStart( aCall ); + + // Swap completed + if( callWithRequest ) + { + callWithRequest->RequestComplete( ECCPErrorNone ); + } + break; + + case CCPCall::EStateIdle: + AirTimeDurationStop( aCall ); + + if ( callWithRequest && + callWithRequest->Request() == CCCECall::ECCEReplaceActive && + !iConferenceCall->IsPartOfConference( *aCall ) && + !GetCall( CCPCall::EStateConnected, aCall ) ) + { + error = callWithRequest->DoPendingRequest(); + } + break; + + case CCPCall::EStateHold: + // Check if there is conference call + if( iConferenceCall->EnumerateCalls() != 0 ) + { + // Do nothing when there is only cscalls + + if ( IsCsPlugin( aCall, ETrue ) ) + { + + break; + } + + // If call or conferencecall isn`t cscall then do conference swap + if( iConferenceCall->State() == MCCEConferenceCallObserver::ECCEConferenceHold && + !iConferenceCall->IsPartOfConference( *aCall ) ) + { + iConferenceCall->Swap(); + } + break; + } + + // Swap 1/2 point ( two calls in hold ) if there isnt connected call allready + call = GetCall( CCPCall::EStateHold, aCall ); + if( call && !GetCall( CCPCall::EStateConnected, aCall ) ) + { + + if ( IsCsPlugin( call, EFalse ) && IsCsPlugin( aCall, EFalse ) ) + { + // If there is two cs calls do nothing + } + else + { + error = call->ResumeNoNotify(); + } + + break; + } + + // Answer new call when one(ringing) ongoing + // Answer new call when one(queued) ongoing + // Dial new call when one ongoing. NOTICE: Idle! + if( callWithRequest ) + { + error = callWithRequest->DoPendingRequest(); + } + break; + + default: + CCELOGSTRING2("CCCECallContainer::HandleCallStatusChange: \ + Unhandled state = %d", aState ); + break; + } + + if( error != KErrNone ) + { + // Do some error handling + } + if ( aNotify != CCECallEnums::ENoNotify ) + { + iCallStateMediator->UpdateCallInfos(); + } + CCELOGSTRING( "CCCECallContainer::HandleCallStatusChange(): OUT" ); + } + +// ----------------------------------------------------------------------------- +// contained call has failed +// ----------------------------------------------------------------------------- +// +void CCCECallContainer::ErrorOccurred( CCCECall* aCall, TCCPError aError ) + { + + CCCECall* callWithRequest = GetCallWithActiveRequest( aCall ); + if( callWithRequest ) + { + // When swap fails try to resume call with request + if( callWithRequest->Request() == CCCECall::ECCESwap && + aCall != callWithRequest && + !GetCall( CCPCall::EStateConnected, NULL ) ) + { + callWithRequest->ResumeNoNotify(); + } + if( aError == ECCPLocalHoldFail && + callWithRequest->Request() == CCCECall::ECCEDial && + CCPCall::ECallTypePS != callWithRequest->Parameters().CallType() ) + { + callWithRequest->RequestComplete( ECCPErrorAlreadyInUse ); + } + else + { + callWithRequest->RequestComplete( aError ); + } + } + } + +// ----------------------------------------------------------------------------- +// Search for first available callinfo call id and save it to array. +// ----------------------------------------------------------------------------- +// +void CCCECallContainer::ReserveCallInfoCallId( TInt aCallId ) + { + for ( TInt i = 0; i < KCCECallObjects; i++ ) + { + if ( KErrNotFound == iCallInfoCallId[ i ] ) + { + iCallInfoCallId[ i ] = aCallId; + break; + } + } + } + +// ----------------------------------------------------------------------------- +// Release call's call id. +// ----------------------------------------------------------------------------- +// +void CCCECallContainer::ReleaseCallInfoCallId( TInt aCallId ) + { + // Clear CallInfoCallId from array. + for ( TInt i = 0; i < KCCECallObjects; i++ ) + { + if ( iCallInfoCallId[ i ] == aCallId ) + { + iCallInfoCallId[ i ] = KErrNotFound; + break; + } + } + } + +// ----------------------------------------------------------------------------- +// Get call object by call id +// ----------------------------------------------------------------------------- +// +CCCECall* CCCECallContainer::GetCall( TInt aCallId ) const + { + if(iCallArray->Count()>aCallId) + { + return iCallArray->At( aCallId ); + } + else + { + return NULL; + } + } + +// ----------------------------------------------------------------------------- +// Get call durations +// ----------------------------------------------------------------------------- +// +void CCCECallContainer::GetAirTimeDuration( TTimeIntervalSeconds& aCSDuration, + TTimeIntervalSeconds& aPSDuration) + { + CCELOGSTRING("CCCECallContainer::GetAirTimeDuration()"); + aCSDuration = iCSDuration->NumberOfBeats(); + aPSDuration = iPSDuration->NumberOfBeats(); + } + +// ----------------------------------------------------------------------------- +// TerminateAllButRingingAndQueuedCalls +// ----------------------------------------------------------------------------- +// +void CCCECallContainer::TerminateAllButRingingAndQueuedCalls() + { + CCELOGSTRING("CCCECallContainer::TerminateAllButRingingAndQueuedCalls():IN"); + + for( TInt i = 0; i < KCCECallObjects; i++ ) + { + CCCECall* call = GetCall( i ); + if( call->IsInUse() && + call->State() != CCPCall::EStateQueued && + call->State() != CCPCall::EStateRinging && + !iConferenceCall->IsPartOfConference( *call ) ) + { + // Quiet hangup + switch( call->State() ) + { + case CCPCall::EStateDialling: + call->GetCCPCall().Cancel(); + break; + case CCPCall::EStateAnswering: + call->GetCCPCall().Reject(); + break; + default: + call->GetCCPCall().HangUp(); + break; + } + + } + } + + if( iConferenceCall->EnumerateCalls() ) + { + iConferenceCall->HangUp(); + } + + + CCELOGSTRING("CCCECallContainer::TerminateAllButRingingAndQueuedCalls():OUT"); + } +// ----------------------------------------------------------------------------- +// TerminateAllCalls +// ----------------------------------------------------------------------------- +// +void CCCECallContainer::TerminateAllCalls() + { + CCELOGSTRING("CCCECallContainer::TerminateAllCalls():IN"); + + for( TInt i = 0; i < KCCECallObjects; i++ ) + { + CCCECall* call = GetCall( i ); + + if( call->IsInUse() && + !iConferenceCall->IsPartOfConference( *call ) ) + { + // Quiet hangup + switch( call->State() ) + { + case CCPCall::EStateDialling: + call->GetCCPCall().Cancel(); + break; + case CCPCall::EStateAnswering: + case CCPCall::EStateRinging: + case CCPCall::EStateQueued: + call->GetCCPCall().Reject(); + break; + default: + call->GetCCPCall().HangUp(); + break; + } + } + + } + + if( iConferenceCall->EnumerateCalls() ) + { + iConferenceCall->HangUp(); + } + + CCELOGSTRING("CCCECallContainer::TerminateAllCalls():OUT"); + } + +// ----------------------------------------------------------------------------- +// TerminateAllVoIPCalls +// ----------------------------------------------------------------------------- +// +void CCCECallContainer::TerminateAllVoIPCalls() + { + CCELOGSTRING("CCCECallContainer::TerminateAllVoIPCalls():IN"); + + for( TInt i = 0; i < KCCECallObjects; i++ ) + { + CCCECall* call = GetCall( i ); + + //Only VoIP calls are terminated + if( call->IsInUse() && + !iConferenceCall->IsPartOfConference( *call ) && + !IsCsPlugin( call, ETrue ) ) + { + // Quiet hangup + switch( call->State() ) + { + case CCPCall::EStateDialling: + call->GetCCPCall().Cancel(); + break; + case CCPCall::EStateAnswering: + case CCPCall::EStateRinging: + case CCPCall::EStateQueued: + call->GetCCPCall().Reject(); + break; + default: + call->GetCCPCall().HangUp(); + break; + } + } + + } + + //Hang up VoIP conference + if( iConferenceCall->EnumerateCalls() && + iConferenceCall->Parameters().CallType() == + CCPCall::ECallTypePS ) + { + iConferenceCall->HangUp(); + } + + CCELOGSTRING("CCCECallContainer::TerminateAllVoIPCalls():OUT"); + } + +// ----------------------------------------------------------------------------- +// Return CCE observer +// ----------------------------------------------------------------------------- +// +MCCEObserver* CCCECallContainer::CCEObserver() + { + return iMCCEObserver; + } + +// ----------------------------------------------------------------------------- +// Return ss observer +// ----------------------------------------------------------------------------- +// +MCCESsObserver* CCCECallContainer::SsObserver() + { + return iMCCESsObserver; + } + + + +// ----------------------------------------------------------------------------- +// GetLifeTime() +// ----------------------------------------------------------------------------- +// +TBool CCCECallContainer::GetLifeTime( TDes8& aLifeTimeInfo ) + { + CCELOGSTRING("CCCE::GetLifeTime()"); + + CConvergedCallProvider* plugin = NULL; + + TRAP_IGNORE( plugin = iPluginManager->GetPluginL(KCSServiceId)); + + if( plugin ) + { + plugin->GetLifeTime(aLifeTimeInfo); + } + else + { + CCELOGSTRING("CCCE::GetLifeTime() - CS plugin not found!"); + return EFalse; + } + + return ETrue; + } + +// ----------------------------------------------------------------------------- +// GetCSInfo() +// ----------------------------------------------------------------------------- +// +TBool CCCECallContainer::GetCSInfo( CSInfo& aCSInfo ) + { + CCELOGSTRING("CCCE::GetCSInfo()"); + + CConvergedCallProvider* plugin = NULL; + + TRAP_IGNORE( plugin = iPluginManager->GetPluginL(KCSServiceId)); + + + if( plugin ) + { + plugin->GetCSInfo(aCSInfo); + } + else + { + CCELOGSTRING("CCCE::GetCSInfo() - CS plugin not found!"); + return EFalse; + } + + return ETrue; + } + +// --------------------------------------------------------------------------- +// CCCECallContainer::IsCsPlugin +// --------------------------------------------------------------------------- +// +TBool CCCECallContainer::IsCsPlugin(CCCECall* aCall, TBool aConference ) const + { + TBool isCsPlugin( EFalse ); + if ( FeatureManager::FeatureSupported( KFeatureIdFfVoiceCallContinuity ) ) + { + if ( aCall->Parameters().CallType() != + CCPCall::ECallTypePS ) + { + isCsPlugin = ETrue; + if( aConference && + iConferenceCall->Parameters().CallType() == + CCPCall::ECallTypePS ) + { + isCsPlugin = EFalse; + } + } + } + else + { + if( aCall->ImplementationUid() == KCSProviderUid ) + { + isCsPlugin = ETrue; + } + } + return isCsPlugin; + } + + +//end of file