mmsharing/mmshengine/src/musengmceoutsession.cpp
changeset 0 f0cf47e981f9
child 2 b31261fd4e04
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mmsharing/mmshengine/src/musengmceoutsession.cpp	Thu Dec 17 08:44:37 2009 +0200
@@ -0,0 +1,501 @@
+/*
+* Copyright (c) 2005 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: 
+*
+*/
+
+
+// USER
+#include "musengmceoutsession.h"
+#include "musengoutsessionobserver.h"
+#include "musenglivesessionobserver.h"
+#include "mussettings.h"
+#include "musengmceutils.h"
+#include "musenguriparser.h"
+#include "musenglogger.h"
+#include "mussesseioninformationapi.h"
+#include "mussipprofilehandler.h"
+
+// SYSTEM
+#include <mcestreambundle.h>
+#include <mcemediastream.h>
+#include <mceoutsession.h>
+#include <mcevideostream.h>
+#include <mcemediasource.h>
+#include <mcefilesource.h>
+#include <mcemediasink.h>
+#include <mcertpsink.h>
+#include <mcespeakersink.h>
+#include <mcedisplaysink.h>
+#include <mcevideocodec.h>
+#include <mceaudiocodec.h>
+
+#include <sipprofile.h>
+#include <sipextensionheader.h>
+#include <sipaddress.h>
+#include <uri8.h>
+#include <e32property.h>
+
+
+
+const TInt KMusEngSipReasonCodeBadRequest = 400;
+const TInt KMusEngSipReasonCodeUnauthorized = 401;
+const TInt KMusEngSipReasonCodePaymentRequired = 402;
+const TInt KMusEngSipReasonCodeRecipientNotFound  = 404;
+const TInt KMusEngSipReasonCodeProxyAuthenticationRequired = 407;
+const TInt KMusEngSipReasonCodeRequestTimeout = 408;
+const TInt KMusEngSipReasonCodeUnsupportedMediaType = 415;
+const TInt KMusEngSipReasonCodeUnsupportedUriScheme = 416;
+const TInt KMusEngSipReasonCodeTemporarilyNotAvailable = 480;
+const TInt KMusEngSipReasonCodeBusyHere = 486;
+const TInt KMusEngSipReasonCodeRequestCancelled = 487;
+const TInt KMusEngSipReasonCodeNotAcceptableHere = 488;
+const TInt KMusEngSipReasonCodeDecline = 603;
+const TInt KMusEngSipReasonCodeNotAcceptable = 606;
+// The next code represents unofficial sip error code
+// "479 Regretfuly, we were not able to process the URI (479/SL)
+const TInt KMusEngSipReasonCode479NotAbleToProcessURI = 479;
+
+const TUint8 KMusEngPayloadTypeVideoH263 = 96;
+const TUint8 KMusEngPayloadTypeAudio = 97;
+const TUint8 KMusEngPayloadTypeVideoAvc = 98;
+
+using namespace NMusSessionInformationApi;
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+CMusEngMceOutSession::~CMusEngMceOutSession()
+    {
+    MUS_LOG( "mus: [ENGINE]  -> CMusEngMceOutSession::~CMusEngMceOutSession()" )
+
+    delete iRecipient;
+    delete iVideoCodecList;
+    
+    MUS_LOG( "mus: [ENGINE]  <- CMusEngMceOutSession::~CMusEngMceOutSession()" )
+    }
+
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CMusEngMceOutSession::InviteL( const TDesC& aRecipient )
+    {
+    MUS_LOG( "mus: [ENGINE]  -> CMusEngMceOutSession::InviteL()")
+
+    if ( iSession )
+        {
+        MUS_ENG_LOG_SESSION_STATE( *iSession ) 
+
+        if ( iSession->State() == CMceSession::EIdle ||
+             iSession->State() == CMceSession::ETerminated )
+            {
+            // This is the case when last invite has ended up to an error,
+            // last sharing has ended normally, or construction of the session
+            // stucture has not been completed. Delete old session and try to
+            // continue normally.
+            delete iSession;
+            iSession = NULL;
+            MUS_LOG( "mus: [ENGINE]     Existing session deleted")
+            }
+        else
+            {
+            // Session is already ongoing. Leave.
+            User::Leave( KErrAlreadyExists );
+            }
+
+        }
+
+    MUS_LOG_TDESC( "mus: [ENGINE]      CMusEngMceOutSession::InviteL() recipient=",
+                   aRecipient )
+
+    // delete possibly existing recipient
+    delete iRecipient;
+    iRecipient = NULL;  
+    
+    TMusEngUriParser parser( aRecipient ); 
+    parser.ParseUriL();    
+    iRecipient = parser.GetUri8L();
+
+    CreateMceSessionStructureL();
+
+    EstablishSessionL();
+
+    MUS_LOG( "mus: [ENGINE]  <- CMusEngMceOutSession::InviteL()")
+    }
+
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CMusEngMceOutSession::CancelInviteL()
+    {
+    MUS_LOG( "mus: [ENGINE]  -> CMusEngMceOutSession::CancelInviteL()" )
+
+    __ASSERT_ALWAYS( iSession, User::Leave( KErrNotReady ) );
+    
+    MUS_ENG_LOG_SESSION_STATE( *iSession ) 
+
+    if( iSession->State() == CMceSession::EOffering )
+        {
+        MUS_LOG( "mus: [ENGINE]     CMceOutSession->CancelL()" )
+        static_cast<CMceOutSession*>( iSession )->CancelL();
+        }
+
+    MUS_LOG( "mus: [ENGINE]  <- CMusEngMceOutSession::CancelInviteL()" )
+    }
+
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CMusEngMceOutSession::SetSupportedVideoCodecListL( 
+                                                const TDesC& aVideoCodecs )
+    {
+    MUS_LOG_TDESC( "mus: [ENGINE]  -> CMusEngMceOutSession::SetSupportedVideoCodecListL: ",
+                   aVideoCodecs )
+
+    HBufC8* newVideoCodecList = 
+                    CnvUtfConverter::ConvertFromUnicodeToUtf8L( aVideoCodecs );
+    delete iVideoCodecList;
+    iVideoCodecList = newVideoCodecList;
+
+    MUS_LOG( "mus: [ENGINE]  <- CMusEngMceOutSession::SetSupportedVideoCodecListL" )
+    }
+
+
+// -----------------------------------------------------------------------------
+// Calls MCE function EstablishL with feature tag in Accept-Contact header.
+// Adjusts stream and codec values.
+// -----------------------------------------------------------------------------
+//
+void CMusEngMceOutSession::EstablishSessionL()
+    {
+    MUS_LOG( "mus: [ENGINE]  -> CMusEngMceOutSession::EstablishSessionL()" )
+    
+    __ASSERT_ALWAYS( iSession, User::Leave( KErrNotReady ) );
+    
+    AdjustStreamsAndCodecsL();
+    
+    CDesC8Array* headers = new ( ELeave ) CDesC8ArrayFlat( 1 );
+    CleanupStack::PushL( headers );
+    headers->AppendL( KMusEngAcceptContactHeader() );
+    headers->AppendL( KMusAcceptHeader() ); 
+    if ( iOperatorVariant )
+        {
+        CUri8* originator = iSipProfileHandler->UserFromProfileLC();
+        
+        CSIPExtensionHeader* header = CSIPExtensionHeader::NewLC( 
+                    KMusPPreferredIdentity, originator->Uri().UriDes() );
+        HBufC8* headInText = header->ToTextL();
+        MUS_LOG_TDESC8( " mus: [ENGINE] P-Preferred-Identity header : ", headInText->Des() );
+        CleanupStack::PopAndDestroy( header );
+        CleanupStack::PopAndDestroy( originator );
+        CleanupStack::PushL( headInText );
+        headers->AppendL( *headInText );
+        CleanupStack::PopAndDestroy( headInText );
+        }
+      
+     /* Add the privacy header if cs call privacy setting is switched on */
+    if ( iPrivate && iPrivateNumber )
+        {
+        AddPrivacyHeaderL( *headers );
+        }
+    static_cast<CMceOutSession*>( iSession )->EstablishL( 0, headers );
+    CleanupStack::Pop( headers );
+    
+    MUS_LOG( "mus: [ENGINE]  <- CMusEngMceOutSession::EstablishSessionL()" )
+    }
+
+
+// -----------------------------------------------------------------------------
+// Handle MCE session termination. Called by MCE observer function of the
+// base class.
+// -----------------------------------------------------------------------------
+//
+void CMusEngMceOutSession::HandleTermination( TInt aStatusCode,
+                                              const TDesC8& aReasonPhrase )
+    {
+    MUS_LOG( "mus: [ENGINE]  -> CMusEngMceOutSession::HandleTermination()" )
+
+    switch ( aStatusCode )
+        {
+
+        case KMusEngSipReasonCodeBadRequest :
+            {
+            iOutSessionObserver.SessionBadRequest();
+            break;
+            }
+        case KMusEngSipReasonCodeUnauthorized :
+            {
+            iOutSessionObserver.SessionUnauthorized();
+            break;
+            }
+        case KMusEngSipReasonCodePaymentRequired :
+            {
+            iOutSessionObserver.SessionPaymentRequired();
+            break;
+            }
+        case KMusEngSipReasonCodeRecipientNotFound : 
+            //lint -fallthrough
+        case KMusEngSipReasonCode479NotAbleToProcessURI:
+            //lint -fallthrough
+        case KMusEngSipReasonCodeUnsupportedUriScheme : 
+            {
+            iOutSessionObserver.SessionRecipientNotFound();
+            break;
+            }
+        case KMusEngSipReasonCodeProxyAuthenticationRequired :
+            {
+            iOutSessionObserver.SessionProxyAuthenticationRequired();
+            break;
+            }
+        case KMusEngSipReasonCodeRequestTimeout :
+            {
+            iOutSessionObserver.SessionRequestTimeOut();
+            break;
+            }
+        case KMusEngSipReasonCodeUnsupportedMediaType :
+            //lint -fallthrough
+        case KMusEngSipReasonCodeNotAcceptableHere:
+            //lint -fallthrough
+        case KMusEngSipReasonCodeNotAcceptable:
+            {
+            iOutSessionObserver.SessionUnsupportedMediaType();
+            break;
+            }
+        case KMusEngSipReasonCodeBusyHere :
+            {
+            // Operator variant uses 486 to rejection instead of 603
+            if ( iOperatorVariant )
+                {
+                iOutSessionObserver.SessionRejected();
+                }
+            else
+                {
+                iOutSessionObserver.SessionBusyHere();
+                }
+            break;
+            }
+        case KMusEngSipReasonCodeRequestCancelled :  
+            {
+            iOutSessionObserver.SessionRequestCancelled();
+            break;
+            }
+        case KMusEngSipReasonCodeDecline :
+            {
+            iOutSessionObserver.SessionRejected();
+            break;
+            }
+        case KMusEngSipReasonCodeTemporarilyNotAvailable :
+            {
+            iOutSessionObserver.SessionTemporarilyNotAvailable();
+            break;
+            }
+        default:
+            {
+            // Termination reason is not outsession specific.
+            // Let the base class to handle the termination.
+            CMusEngMceSession::HandleTermination( aStatusCode, aReasonPhrase );
+            }
+        }
+
+
+    MUS_LOG( "mus: [ENGINE]  <- CMusEngMceOutSession::HandleTermination()" )
+    }
+
+
+// -----------------------------------------------------------------------------
+// Sets payload type and calls overridden base class version
+// -----------------------------------------------------------------------------
+//
+void CMusEngMceOutSession::AdjustVideoCodecL( CMceVideoCodec& aVideoCodec )
+    {
+    MUS_LOG( "mus: [ENGINE]  -> CMusEngMceOutSession::AdjustVideoCodecL()" )
+    
+    CMusEngMceSession::AdjustVideoCodecL( aVideoCodec );
+    
+    if ( aVideoCodec.SdpName() == KMceSDPNameH263() ||
+         aVideoCodec.SdpName() == KMceSDPNameH2632000() )
+        {
+        User::LeaveIfError( 
+                aVideoCodec.SetPayloadType( KMusEngPayloadTypeVideoH263 ) );
+        }
+    else if ( aVideoCodec.SdpName() == KMceSDPNameH264() )
+        {
+        User::LeaveIfError(
+                aVideoCodec.SetPayloadType( KMusEngPayloadTypeVideoAvc ) );
+        }
+    else
+        {
+        // NOP
+        }
+    
+    MUS_LOG( "mus: [ENGINE]  <- CMusEngMceOutSession::AdjustVideoCodecL()" )
+    }
+
+
+// -----------------------------------------------------------------------------
+// Sets payload type and calls overridden base class version
+// -----------------------------------------------------------------------------
+//        
+void CMusEngMceOutSession::AdjustAudioCodecL( CMceAudioCodec& aAudioCodec )
+    {
+    MUS_LOG( "mus: [ENGINE]  -> CMusEngMceOutSession::AdjustAudioCodecL()" )
+    
+    CMusEngMceSession::AdjustAudioCodecL( aAudioCodec );
+    
+    User::LeaveIfError( aAudioCodec.SetPayloadType( KMusEngPayloadTypeAudio ) );
+    
+    MUS_LOG( "mus: [ENGINE]  <- CMusEngMceOutSession::AdjustAudioCodecL()" )
+    }
+        
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+CMusEngMceOutSession::CMusEngMceOutSession( 
+                                const TRect& aRect,
+                                MMusEngSessionObserver& aSessionObserver,
+                                MMusEngOutSessionObserver& aOutSessionObserver )
+    : CMusEngMceSession( aRect, aSessionObserver ),      
+      iOutSessionObserver( aOutSessionObserver )
+    {
+    }
+
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+void CMusEngMceOutSession::ConstructL( TUint aSipProfileId )
+    {
+    MUS_LOG( "mus: [ENGINE]  -> CMusEngMceOutSession::ConstructL()" )
+
+    CMusEngMceSession::ConstructL();
+    iSipProfileHandler->CreateProfileL( aSipProfileId );
+    
+    // Check if feature specific behavior is expected
+    iPrivate = ( MultimediaSharingSettings::PrivacySetting());
+        
+    NMusSessionInformationApi::TMusClirSetting clir;
+    // Ignore RProperty::Get return value.Incase of error it should behave default.
+    RProperty::Get( NMusSessionInformationApi::KCategoryUid,
+                    NMusSessionInformationApi::KMusClirSetting,
+                    reinterpret_cast<TInt&>( clir ) );
+    iPrivateNumber = ( clir == NMusSessionInformationApi::ESendOwnNumber )? EFalse: ETrue;
+      
+    MUS_LOG( "mus: [ENGINE]  <- CMusEngMceOutSession::ConstructL()" )
+    }
+
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+void CMusEngMceOutSession::CreateMceSessionStructureL()
+    {
+    MUS_LOG( "mus: [ENGINE]  -> CMusEngMceOutSession::CreateMceSessionStructureL()" )
+
+ 	CSIPProfile* profile = iSipProfileHandler->Profile();
+    __ASSERT_ALWAYS( profile != NULL, User::Leave( KErrNotReady ) );
+
+    // Create session
+    if ( iPrivate && iPrivateNumber )
+        {
+        HBufC8* originator = KMusAnonymousHeader().AllocLC();
+        iSession = CMceOutSession::NewL( *iManager, *profile, *iRecipient, originator );
+        CleanupStack::Pop();
+        }
+    else
+        {
+        iSession = CMceOutSession::NewL( *iManager, *profile, *iRecipient );
+        }
+
+
+    // Remove QoS-lines if needed
+    if ( profile->Type().iSIPProfileClass == 
+         TSIPProfileTypeInfo::EInternet ||
+         MultimediaSharingSettings::ForceInternetSignalingSettingL() ==
+         MusSettingsKeys::EForceInternetSignaling ||
+         iOperatorVariant)
+        {
+        iSession->SetModifierL( KMcePreconditions, KMcePreconditionsNotUsed );
+        MUS_LOG( "mus: [ENGINE]     Usage of preconditions denied" )
+        }
+        
+    SetSessionSdpLinesL( *iSession );
+
+    // Create bundle for local streams
+    
+    CMceStreamBundle* localBundle = 
+                        CMceStreamBundle::NewLC( CMceStreamBundle::ELS );
+
+    // To complete session structure, let the sibling classes add video out
+    // and possibly needed audio streams
+    CompleteSessionStructureL( *localBundle );
+
+    // Create stream to display and share source with video outstream
+    CMceVideoStream* streamForDisplay = CMceVideoStream::NewLC();
+
+    CMceVideoStream* videoOut = MusEngMceUtils::GetVideoOutStreamL( *iSession );
+    
+    SetMediaSdpLinesL( *videoOut );
+		
+    streamForDisplay->SetSourceL( videoOut->Source() );
+
+    MusEngMceUtils::AddDisplayL( *streamForDisplay, *iManager, Rect() );
+
+    iSession->AddStreamL( streamForDisplay );
+    CleanupStack::Pop( streamForDisplay );    
+
+    // Check if there are audio streams to bundle with
+    if ( localBundle->Streams().Count() > 0 ) 
+        {
+        localBundle->AddStreamL( *streamForDisplay );
+        iSession->AddBundleL( localBundle );
+        CleanupStack::Pop( localBundle );
+        }
+    else
+        {
+        CleanupStack::PopAndDestroy( localBundle );
+        }
+
+    MUS_LOG( "mus: [ENGINE]  <- CMusEngMceOutSession::CreateMceSessionStructureL()" )
+    }
+
+
+// -----------------------------------------------------------------------------
+// Add Privacy header if own phone number/id should not be sent to remote party
+// -----------------------------------------------------------------------------
+//
+void CMusEngMceOutSession::AddPrivacyHeaderL( CDesC8Array& aHeaders )
+    {
+    MUS_LOG( "mus: [ENGINE]  -> AddPrivacyHeaderL()" )
+    _LIT8( KMusPrivacyHeaderValue, "id" );
+    CSIPExtensionHeader* header = CSIPExtensionHeader::NewLC( 
+                                  KMusPrivacyHeader, KMusPrivacyHeaderValue );
+    HBufC8* headInText = header->ToTextL();
+    MUS_LOG_TDESC8( " mus: [ENGINE] Privacy header : ", headInText->Des() );
+    CleanupStack::PopAndDestroy( header );
+    CleanupStack::PushL( headInText );
+    aHeaders.AppendL( *headInText );
+    CleanupStack::PopAndDestroy( headInText );
+    MUS_LOG( "mus: [ENGINE]  <- AddPrivacyHeaderL()" )
+    }