convergedcallengine/cce/src/cccetransfercontroller.cpp
changeset 0 ff3b6d0fd310
--- /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