diff -r 000000000000 -r ff3b6d0fd310 convergedcallengine/cce/src/cccetransfercontroller.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/convergedcallengine/cce/src/cccetransfercontroller.cpp Tue Feb 02 01:11:09 2010 +0200 @@ -0,0 +1,447 @@ +/* +* Copyright (c) 2007-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: Contains transfer handling logic +* +*/ + +#include "cccelogger.h" +#include "cccetransfercontroller.h" +#include "cccecallcontainer.h" +#include "cccecall.h" +#include "mccpcall.h" +#include "mccpcscall.h" +#include "mccecallobserver.h" + +// ======== MEMBER FUNCTIONS ======== + + +// --------------------------------------------------------------------------- +// Constructor +// --------------------------------------------------------------------------- +// +CCCETransferController::CCCETransferController( + CCCECallContainer& aCallContainer ) : + iCallContainer( aCallContainer ) + { + Reset(); + } + +// --------------------------------------------------------------------------- +// CCCETransferController::NewL +// --------------------------------------------------------------------------- +// +CCCETransferController* CCCETransferController::NewL( + CCCECallContainer& aCallContainer ) + { + CCCETransferController* self = new( ELeave ) CCCETransferController( + aCallContainer ); + return self; + } + +// --------------------------------------------------------------------------- +// Destructor +// --------------------------------------------------------------------------- +// +CCCETransferController::~CCCETransferController() + { + Reset(); + } + +// --------------------------------------------------------------------------- +// CCCETransferController::ErrorOccurred +// --------------------------------------------------------------------------- +// +void CCCETransferController::ErrorOccurred( + const TCCPError aError, MCCPCall* /*aCall*/ ) + { + CCELOGSTRING2("CCCETransferController::ErrorOccurred() aError=%d", aError); + (void) aError; // remove urel compile warning + } + +// --------------------------------------------------------------------------- +// CCCETransferController::CallStateChanged +// --------------------------------------------------------------------------- +// +void CCCETransferController::CallStateChanged( + const MCCPCallObserver::TCCPCallState aState, MCCPCall* /*aCall*/ ) + { + CCELOGSTRING2("CCCETransferController::CallStateChanged():IN \ + aState=%d", aState); + + switch ( aState ) + { + case ECCPStateIdle: + { + CCELOGSTRING("CCCETransferController::CallStateChanged: ECCPStateIdle"); + if ( iOriginatorCall && iObservedCall == iOriginatorCall ) + { + CCELOGSTRING("CCCETransferController::CallStateChanged: Idle -> release original call"); + iCallContainer.ReleaseCall( *iOriginatorCall, iOriginatorCall->Uid() ); + iOriginatorCall = NULL; + iObservedCall = NULL; + } + else if ( iTransferCall && iObservedCall == iTransferCall ) + { + CCELOGSTRING("CCCETransferController::CallStateChanged: Idle -> release transfer call"); + iCallContainer.ReleaseCall( *iTransferCall, iTransferCall->Uid() ); + iTransferCall = NULL; + iObservedCall = NULL; + } + } + break; + case ECCPStateConnected: + { + CCELOGSTRING("CCCETransferController::CallStateChanged: ECCPStateConnected "); + CCCECall* originator = iCallContainer.GetCall( iOriginatorCall ); + + if ( !originator || + ( originator->State() != CCPCall::EStateHold && + originator->State() != CCPCall::EStateConnected ) ) + { + // Originator disconnected or released. + // Terminate transfer call. + TInt err = iTransferCall->HangUp(); + if ( err ) + { + ReleaseTransferCall(); + } + + } + else if ( ECCETypeAttendedMO == iOngoingTransferType ) + { + // Transfer call was connected + // Swap transfer call with original call and hangup&release + // original call + + + TRAPD( err, + originator->SetConvergedCallL( iTransferCall, + iTransferCall->Uid(), ETrue ); + iTransferCall->RemoveObserver( *this ); + iTransferCall->AddObserverL( *originator ); + iOriginatorCall->RemoveObserver( *originator ); + iOriginatorCall->AddObserverL( *this ); ); + + + + iObservedCall = iOriginatorCall; + + if ( KErrNone == err ) + { + // If original call was on hold, new call must be on hold also + if ( ECCPStateHold == originator->State() ) + { + iTransferCall->Hold(); + } + + // New call is no more on hold by remote end + static_cast(originator)->CallEventOccurred( ECCPRemoteResume, + &originator->GetCCPCall() ); + } + else + { + CCELOGSTRING2("CCCETransferController::CallStateChanged():transfer error=%d", + err); + } + } + else if ( ECCETypeAttendedMT == iOngoingTransferType ) + { + + // Set new transferred call to original CCECall object + TRAP_IGNORE( originator->SetConvergedCallL( iTransferCall, + iTransferCall->Uid(), ETrue ) ); + + + // Release original call + iOriginatorCall->RemoveObserver( *originator ); + TRAP_IGNORE( iOriginatorCall->AddObserverL( *this ) ); + + iObservedCall = iOriginatorCall; + iOriginatorCall->HangUp(); + } + } + break; + default: + CCELOGSTRING2("CCCETransferController::CallStateChanged: \ + Unhandled state = %d",aState ); + break; + } + CCELOGSTRING("CCCETransferController::CallStateChanged():OUT"); + } + +// --------------------------------------------------------------------------- +// CallStateChangedWithInband( TCCPCallState aState ) +// --------------------------------------------------------------------------- +// +void CCCETransferController::CallStateChangedWithInband( TCCPCallState aState, + MCCPCall* aCall ) + { + CCELOGSTRING("CCCETransferController::CallStateChangedWithInband()"); + CallStateChanged( aState, aCall ); + } + +// --------------------------------------------------------------------------- +// CCCETransferController::CallEventOccurred +// --------------------------------------------------------------------------- +// +void CCCETransferController::CallEventOccurred( + const MCCPCallObserver::TCCPCallEvent /*aEvent*/, MCCPCall* /*aCall*/ ) + { + CCELOGSTRING("CCCETransferController::CallEventOccurred()"); + } + +// --------------------------------------------------------------------------- +// CCCETransferController::CallCapsChanged +// --------------------------------------------------------------------------- +// +void CCCETransferController::CallCapsChanged( const TUint32 /*aCapsFlags*/, + MCCPCall* /*aCall*/ ) + { + CCELOGSTRING("CCCETransferController::CallCapsChanged():"); + } + +// --------------------------------------------------------------------------- +// CCCETransferController::Reset +// --------------------------------------------------------------------------- +// +void CCCETransferController::Reset() + { + CCELOGSTRING("CCCETransferController::Reset()"); + iOriginatorCall = NULL; + iOriginatorCallId = KErrNotFound; + iTransferDialPending = EFalse; + iTransferAccepted = EFalse; + iOngoingTransferType = ECCETypeNone; + iObservedCall = NULL; + } + +// --------------------------------------------------------------------------- +// CCCETransferController::HandleRemoteTransferRequest +// --------------------------------------------------------------------------- +// +void CCCETransferController::HandleRemoteTransferRequest( + MCCPCall* aNewTransferCall, + MCCPCall* aOriginator, + TBool aAttented ) + { + CCELOGSTRING("CCCETransferController::HandleTransferRequest():IN"); + + CCCECall* originator = iCallContainer.GetCall( aOriginator ); + if ( originator && + ( originator->State() == CCPCall::EStateHold || + originator->State() == CCPCall::EStateConnected ) ) + { + iOriginatorCall = aOriginator; + iTransferCall = aNewTransferCall; + + // Unattended case + if ( !aAttented ) + { + CCELOGSTRING("CCCETransferController::HandleTransferRequest() unattended "); + iOriginatorCallId = originator->CallId(); + iOngoingTransferType = ECCETypeUnattended; + originator->HandleTransfer( aAttented, *this ); + } + // Attended case + else + { + CCELOGSTRING("CCCETransferController::HandleTransferRequest() attended "); + originator->SetTransferController( this ); + iOngoingTransferType = ECCETypeAttendedMO; + TRAP_IGNORE( iTransferCall->AddObserverL( *this ) ); + + iObservedCall = iTransferCall; + TInt error = iTransferCall->Dial(); + + if( error ) + { + CCELOGSTRING2("CCCETransferController: \ + dial error: %d", error); + ReleaseTransferCall(); + } + } + } + else + { + CCELOGSTRING("CCCETransferController: Originator call not found!"); + iCallContainer.ReleaseCall( *aNewTransferCall ); + } + + CCELOGSTRING("CCCETransferController::HandleTransferRequest():OUT"); + } + +// --------------------------------------------------------------------------- +// CCCETransferController::TransferCallIncoming +// --------------------------------------------------------------------------- +// +void CCCETransferController::TransferCallIncoming( MCCPCall* aNewTransferCall, + MCCPCall* aOriginator ) + { + CCELOGSTRING("CCCETransferController::TransferCallIncoming():IN"); + iTransferCall = aNewTransferCall; + iOriginatorCall = aOriginator; + + CCCECall* originator = iCallContainer.GetCall( aOriginator ); + if ( originator ) + { + originator->SetTransferController( this ); + + iOngoingTransferType = ECCETypeAttendedMT; + + TInt err = KErrNone; + TRAP( err, iTransferCall->AddObserverL( *this ) ); + if ( KErrNone == err ) + { + iObservedCall = iTransferCall; + // Answer new call when this gets connected original call will be terminated + TInt err = iTransferCall->Answer(); + + if ( KErrNone != err ) + { + CCELOGSTRING2("CCCETransferController::TransferCallIncoming() Answering failed err=%d", err); + ReleaseTransferCall(); + } + } + } + else + { + CCELOGSTRING("CCCETransferController::TransferCallIncoming() originator not \ + found"); + ReleaseTransferCall(); + } + + CCELOGSTRING("CCCETransferController::TransferCallIncoming():OUT"); + } + +// --------------------------------------------------------------------------- +// CCCETransferController::ReleaseTransferCall +// --------------------------------------------------------------------------- +// + void CCCETransferController::ReleaseTransferCall() + { + CCELOGSTRING("CCCETransferController::ReleaseTransferCall()"); + if ( iTransferCall ) + { + iCallContainer.ReleaseCall(*iTransferCall); + iTransferCall = NULL; + Reset(); + CCELOGSTRING("CCCETransferController: TransferCall queued \ + to be released"); + } + } + +// --------------------------------------------------------------------------- +// CCCETransferController::OngoingTransferType +// --------------------------------------------------------------------------- +// +CCCETransferController::TTransferType CCCETransferController::OngoingTransferType() const + { + return iOngoingTransferType; + } + +// --------------------------------------------------------------------------- +// CCCETransferController::TransferCall +// --------------------------------------------------------------------------- +// +MCCPCall* CCCETransferController::TransferCall() const + { + return iTransferCall; + } + +// --------------------------------------------------------------------------- +// CCCETransferController::OriginatorCall +// --------------------------------------------------------------------------- +// +MCCPCall* CCCETransferController::OriginatorCall() const + { + return iOriginatorCall; + } + +// --------------------------------------------------------------------------- +// CCCETransferController::SetTransferAccepted +// --------------------------------------------------------------------------- +// +void CCCETransferController::SetTransferAccepted( TBool aAccepted ) + { + iTransferAccepted = aAccepted; + } + +// --------------------------------------------------------------------------- +// CCCETransferController::TransferAccepted +// --------------------------------------------------------------------------- +// +TBool CCCETransferController::TransferAccepted() const + { + return iTransferAccepted; + } + +// --------------------------------------------------------------------------- +// CCCETransferController::SetTransferDialPending +// --------------------------------------------------------------------------- +// +void CCCETransferController::SetTransferDialPending( TBool aDialPending ) + { + CCELOGSTRING3("CCCETransferController::SetTransferDialPending() \ + iDialPending=%d aDialPending=%d",iTransferDialPending, aDialPending); + iTransferDialPending = aDialPending; + } + +// --------------------------------------------------------------------------- +// CCCETransferController::HandleCallStateChanged +// --------------------------------------------------------------------------- +// +void CCCETransferController::HandleCallStateChanged( CCCECall* aCall, + CCPCall::TCallState aStatus ) + { + CCELOGSTRING2("CCCETransferController::HandleCallStatusChange():IN aStatus=%d", + aStatus); + + switch ( aStatus ) + { + case CCPCall::EStateIdle: + // flow through + case CCPCall::EStateConnected: + { + // When original or new call goes to idle/connected transfercontroller + // can be resetted + if( &aCall->GetCCPCall() == iOriginatorCall || + &aCall->GetCCPCall() == iTransferCall ) + { + Reset(); + } + } + break; + case CCPCall::EStateDisconnecting: + { + // When original call goes to disconnecting state and there + // is unattended transfer dial pending. Start dialing. + if ( &aCall->GetCCPCall() == iOriginatorCall && + iTransferDialPending ) + { + CCCECall* call =iCallContainer.GetCall( iTransferCall ); + if ( call ) + { + iTransferDialPending = EFalse; + call->DoPendingRequest(); + } + } + } + break; + default: + CCELOGSTRING2("CCCETransferController::HandleCallStatusChange: \ + Unhandled state = %d", aStatus ); + } + CCELOGSTRING("CCCETransferController::HandleCallStatusChange():OUT"); + } +// End of file