--- /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 <featmgr.h>
+
+//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<CCCECall>( 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<MCCEConferenceCallObserver&>( aObserver ) );
+ }
+ else
+ {
+ iConferenceCall = CCCEConferenceCall::NewL( *this, *iPluginManager );
+ iConferenceCall->SetObserver(
+ const_cast<MCCEConferenceCallObserver&>( 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<CCCECall>& 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<MCCECallInfo>& 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