--- /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<MCCPCallObserver*>(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