diff -r 000000000000 -r f0cf47e981f9 mmsharing/mmshengine/src/musengmceoutsession.cpp --- /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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + + + +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( 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( 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( 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()" ) + }