mmsharing/mmshengine/src/musengmceoutsession.cpp
changeset 22 496ad160a278
equal deleted inserted replaced
15:ccd8e69b5392 22:496ad160a278
       
     1 /*
       
     2 * Copyright (c) 2005 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description: 
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 // USER
       
    20 #include "musengmceoutsession.h"
       
    21 #include "mussettings.h"
       
    22 #include "musengmceutils.h"
       
    23 #include "musenguriparser.h"
       
    24 #include "musenglogger.h"
       
    25 #include "mussipprofilehandler.h"
       
    26 #include "mussessionproperties.h"
       
    27 #include "musresourceproperties.h"
       
    28 
       
    29 // SYSTEM
       
    30 #include <lcsessionobserver.h>
       
    31 #include <lcuiprovider.h>
       
    32 #include <mcestreambundle.h>
       
    33 #include <mcemediastream.h>
       
    34 #include <mceoutsession.h>
       
    35 #include <mcevideostream.h>
       
    36 #include <mcemediasource.h>
       
    37 #include <mcefilesource.h>
       
    38 #include <mcemediasink.h>
       
    39 #include <mcertpsink.h>
       
    40 #include <mcespeakersink.h>
       
    41 #include <mcedisplaysink.h>
       
    42 #include <mcevideocodec.h>
       
    43 #include <mceaudiocodec.h>
       
    44 #include <e32property.h>
       
    45 
       
    46 #include <sipprofile.h>
       
    47 #include <sipextensionheader.h>
       
    48 #include <sipaddress.h>
       
    49 #include <uri8.h>
       
    50 
       
    51 const TInt KMusEngSipReasonCodeRecipientNotFound  = 404;
       
    52 const TInt KMusEngSipReasonCodeRequestTimeout = 408;
       
    53 const TInt KMusEngSipReasonCodeUnsupportedMediaType = 415;
       
    54 const TInt KMusEngSipReasonCodeUnsupportedUriScheme = 416;
       
    55 const TInt KMusEngSipReasonCodeTemporarilyNotAvailable = 480;
       
    56 const TInt KMusEngSipReasonCodeBusyHere = 486;
       
    57 const TInt KMusEngSipReasonCodeRequestCancelled = 487;
       
    58 const TInt KMusEngSipReasonCodeNotAcceptableHere = 488;
       
    59 const TInt KMusEngSipReasonCodeDecline = 603;
       
    60 const TInt KMusEngSipReasonCodeNotAcceptable = 606;
       
    61 // The next code represents unofficial sip error code
       
    62 // "479 Regretfuly, we were not able to process the URI (479/SL)
       
    63 const TInt KMusEngSipReasonCode479NotAbleToProcessURI = 479;
       
    64 
       
    65 const TUint8 KMusEngPayloadTypeVideoH263 = 96;
       
    66 const TUint8 KMusEngPayloadTypeAudio = 97;
       
    67 const TUint8 KMusEngPayloadTypeVideoAvc = 98;
       
    68 
       
    69 const TInt KMusEngSipAddressMaxLength = 256;
       
    70 const TInt KMusEngSipAddressesMaxAmount  =   8;
       
    71 _LIT( KMusEngCommaSymbol, "," );
       
    72 
       
    73 // -----------------------------------------------------------------------------
       
    74 //
       
    75 // -----------------------------------------------------------------------------
       
    76 //
       
    77 CMusEngMceOutSession::CMusEngMceOutSession()
       
    78     : CMusEngMceSession(),
       
    79       iTriedInvitations( 0 ),
       
    80       iAsyncBrakeCallBack( AsyncBrakeCompleted, this ),
       
    81       iRegistrationCallBack( RegistrationTimerExpired, this ),
       
    82       iInvitationResponseCallBack( InvitationResponseTimerExpired, this )
       
    83     {
       
    84     iAsyncBrakeEntry.Set( iAsyncBrakeCallBack );
       
    85     iRegistrationEntry.Set( iRegistrationCallBack );
       
    86     iInvitationResponseEntry.Set( iInvitationResponseCallBack );
       
    87     }
       
    88 
       
    89 // -----------------------------------------------------------------------------
       
    90 //
       
    91 // -----------------------------------------------------------------------------
       
    92 //
       
    93 void CMusEngMceOutSession::ConstructL()
       
    94     {
       
    95     MUS_LOG( "mus: [ENGINE]  -> CMusEngMceOutSession::ConstructL()" )
       
    96     
       
    97     CMusEngMceSession::ConstructL();
       
    98     TInt sipProfileId;
       
    99     TInt error = KErrNone;
       
   100     error = ( RProperty::Get( NMusSessionApi::KCategoryUid, 
       
   101                              NMusSessionApi::KSipProfileId, sipProfileId ) );
       
   102     if ( error != KErrNone )
       
   103        {
       
   104        sipProfileId = KErrNone;
       
   105        error = KErrNone;
       
   106        }
       
   107     iSipProfileHandler->CreateProfileL( sipProfileId );
       
   108     iVideoCodecList = NULL;
       
   109     TBuf<RProperty::KMaxPropertySize> buffer;
       
   110     error = ( RProperty::Get( NMusSessionApi::KCategoryUid, 
       
   111                                  NMusSessionApi::KVideoCodecs, buffer ) );
       
   112     if ( error == KErrNone && buffer.Length() )
       
   113         {
       
   114         iVideoCodecList = 
       
   115                     CnvUtfConverter::ConvertFromUnicodeToUtf8L( buffer );
       
   116         }
       
   117         
       
   118     iDeltaTimer = CDeltaTimer::NewL( CActive::EPriorityStandard );
       
   119     
       
   120     /* Read the contact name set by availability plugin */    
       
   121     error = RProperty::Get( NMusSessionApi::KCategoryUid,
       
   122                                  NMusSessionApi::KContactName,
       
   123                                  buffer );
       
   124     iRemoteDisplayName = ( error == KErrNone && buffer.Length() ) 
       
   125                          ? buffer.AllocL() : KNullDesC().AllocL();
       
   126     
       
   127     MUS_LOG( "mus: [ENGINE]  <- CMusEngMceOutSession::ConstructL()" )
       
   128     }
       
   129 
       
   130 // -----------------------------------------------------------------------------
       
   131 //
       
   132 // -----------------------------------------------------------------------------
       
   133 //
       
   134 CMusEngMceOutSession::~CMusEngMceOutSession()
       
   135     {
       
   136     MUS_LOG( "mus: [ENGINE]  -> CMusEngMceOutSession::~CMusEngMceOutSession()" )
       
   137  
       
   138     if ( iAddressQueried && iRecipient )
       
   139         {
       
   140         TRAP_IGNORE( SaveContactL( *iRecipient ) )
       
   141         }
       
   142     
       
   143     delete iDeltaTimer;
       
   144     delete iRecipient;
       
   145     delete iVideoCodecList;
       
   146     delete iRemoteSipAddressProposal;
       
   147     delete iRemoteDisplayName;
       
   148     MUS_LOG( "mus: [ENGINE]  <- CMusEngMceOutSession::~CMusEngMceOutSession()" )
       
   149     }
       
   150 
       
   151 // -----------------------------------------------------------------------------
       
   152 // From MLcSession
       
   153 // -----------------------------------------------------------------------------
       
   154 //
       
   155 void CMusEngMceOutSession::EstablishLcSessionL()
       
   156     {
       
   157     MUS_LOG( "mus: [ENGINE]  -> CMusEngMceOutSession::EstablishLcSessionL()")
       
   158 
       
   159     iAddressQueried = EFalse;
       
   160     if ( LcUiProvider() && !IsBackgroundStartup() )
       
   161         {
       
   162         LcUiProvider()->HandleForegroundStatus( ETrue );
       
   163         }
       
   164     TRAPD( err, DoInviteL() );
       
   165         
       
   166     // If address is in wrong format, Manual Address Entry Dialog is displayed
       
   167     if ( ( err == KErrArgument ) && DoSyncRetryL() )
       
   168         {  
       
   169         err = KErrNone; // Doing retry
       
   170         }
       
   171     
       
   172     User::LeaveIfError( err );
       
   173         
       
   174     MUS_LOG( "mus: [ENGINE]  <- CMusEngMceOutSession::EstablishLcSessionL")
       
   175     }
       
   176 
       
   177 // -----------------------------------------------------------------------------
       
   178 // From MLcSession
       
   179 // -----------------------------------------------------------------------------
       
   180 //
       
   181 void CMusEngMceOutSession::TerminateLcSessionL()
       
   182     {
       
   183     MUS_LOG( "mus: [ENGINE]  -> CMusEngMceOutSession::TerminateLcSessionL" )
       
   184 
       
   185     __ASSERT_ALWAYS( iSession, User::Leave( KErrNotReady ) );
       
   186 
       
   187     if( iSession->State() == CMceSession::EOffering )
       
   188         {
       
   189         static_cast< CMceOutSession* >( iSession )->CancelL();
       
   190         }
       
   191     else
       
   192         {
       
   193         iSession->TerminateL();
       
   194         }
       
   195     
       
   196     MUS_LOG( "mus: [ENGINE]  <- CMusEngMceOutSession::TerminateLcSessionL" )
       
   197     }
       
   198 
       
   199 // -----------------------------------------------------------------------------
       
   200 //
       
   201 // -----------------------------------------------------------------------------
       
   202 //
       
   203 void CMusEngMceOutSession::AddDisplayL( CMceMediaStream& aStream )
       
   204     {
       
   205     MusEngMceUtils::AddDisplayL( aStream, *iManager, Rect() );
       
   206     }
       
   207 
       
   208 // -----------------------------------------------------------------------------
       
   209 // Calls MCE function EstablishL with feature tag in Accept-Contact header.
       
   210 // Adjusts stream and codec values.
       
   211 // -----------------------------------------------------------------------------
       
   212 //
       
   213 void CMusEngMceOutSession::EstablishSessionL()
       
   214     {
       
   215     MUS_LOG( "mus: [ENGINE]  -> CMusEngMceOutSession::EstablishSessionL()" )
       
   216     
       
   217     __ASSERT_ALWAYS( iSession, User::Leave( KErrNotReady ) );
       
   218     
       
   219     AdjustStreamsAndCodecsL();
       
   220     
       
   221     CDesC8Array* headers = new ( ELeave ) CDesC8ArrayFlat( 1 );
       
   222     CleanupStack::PushL( headers );
       
   223     headers->AppendL( KMusEngAcceptContactHeader() );
       
   224     headers->AppendL( KMusAcceptHeader() ); 
       
   225     if ( iOperatorVariant )
       
   226         {
       
   227         CUri8* originator = iSipProfileHandler->UserFromProfileLC();
       
   228         
       
   229         CSIPExtensionHeader* header = CSIPExtensionHeader::NewLC( 
       
   230                     KMusPPreferredIdentity, originator->Uri().UriDes() );
       
   231         HBufC8* headInText = header->ToTextL();
       
   232         MUS_LOG_TDESC8( " mus: [ENGINE] P-Preferred-Identity header : ", headInText->Des() );
       
   233         CleanupStack::PopAndDestroy( header );
       
   234         CleanupStack::PopAndDestroy( originator );
       
   235         CleanupStack::PushL( headInText );
       
   236         headers->AppendL( *headInText );
       
   237         CleanupStack::PopAndDestroy( headInText );
       
   238         }
       
   239       
       
   240       
       
   241     static_cast<CMceOutSession*>( iSession )->EstablishL( 0, headers );
       
   242     CleanupStack::Pop( headers );
       
   243     
       
   244     MUS_LOG( "mus: [ENGINE]  <- CMusEngMceOutSession::EstablishSessionL()" )
       
   245     }
       
   246 
       
   247 // -----------------------------------------------------------------------------
       
   248 // Handle MCE session termination. Called by MCE observer function of the
       
   249 // base class.
       
   250 // -----------------------------------------------------------------------------
       
   251 //
       
   252 void CMusEngMceOutSession::HandleTermination( TInt aStatusCode,
       
   253                                               const TDesC8& aReasonPhrase )
       
   254     {
       
   255     MUS_LOG( "mus: [ENGINE]  -> CMusEngMceOutSession::HandleTermination()" )
       
   256 
       
   257     switch ( aStatusCode )
       
   258         {
       
   259         case KMusEngSipReasonCodeRecipientNotFound : 
       
   260             //lint -fallthrough
       
   261         case KMusEngSipReasonCode479NotAbleToProcessURI:
       
   262             //lint -fallthrough
       
   263         case KMusEngSipReasonCodeUnsupportedUriScheme : 
       
   264             {
       
   265             InitRecipientNotFoundHandling();
       
   266             break;
       
   267             }
       
   268         case KMusEngSipReasonCodeRequestTimeout :
       
   269             {
       
   270             InformObserverAboutSessionFailure( MLcSession::ENoAnswer );
       
   271             break;
       
   272             }
       
   273         case KMusEngSipReasonCodeUnsupportedMediaType :
       
   274             //lint -fallthrough
       
   275         case KMusEngSipReasonCodeNotAcceptableHere:
       
   276             //lint -fallthrough
       
   277         case KMusEngSipReasonCodeNotAcceptable:
       
   278             {
       
   279             InformObserverAboutSessionFailure( MLcSession::ESessionRejected );
       
   280             break;
       
   281             }
       
   282         case KMusEngSipReasonCodeBusyHere :
       
   283             {
       
   284             // Operator variant uses 486 to rejection instead of 603
       
   285             if ( iOperatorVariant )
       
   286                 {
       
   287                 InformObserverAboutSessionFailure( 
       
   288                     MLcSession::ESessionRejected );
       
   289                 }
       
   290             else
       
   291                 {
       
   292                 InformObserverAboutSessionFailure( 
       
   293                     MLcSession::ERecipientBusy );
       
   294                 }
       
   295             break;
       
   296             }
       
   297         case KMusEngSipReasonCodeRequestCancelled :  
       
   298             {
       
   299             InformObserverAboutSessionFailure( MLcSession::ESessionCancelled );
       
   300             break;
       
   301             }
       
   302         case KMusEngSipReasonCodeDecline :
       
   303             {
       
   304             InformObserverAboutSessionFailure( MLcSession::ESessionRejected );
       
   305             break;
       
   306             }
       
   307         case KMusEngSipReasonCodeTemporarilyNotAvailable :
       
   308             {
       
   309             InformObserverAboutSessionFailure( 
       
   310                 MLcSession::ERecipientTemporarilyNotAvailable );
       
   311             break;
       
   312             }
       
   313         default:
       
   314             {
       
   315             // Termination reason is not outsession specific.
       
   316             // Let the base class to handle the termination.
       
   317             CMusEngMceSession::HandleTermination( aStatusCode, aReasonPhrase );
       
   318             }
       
   319         }
       
   320 
       
   321 
       
   322     MUS_LOG( "mus: [ENGINE]  <- CMusEngMceOutSession::HandleTermination()" )
       
   323     }
       
   324 
       
   325 // -----------------------------------------------------------------------------
       
   326 // Sets payload type and calls overridden base class version
       
   327 // -----------------------------------------------------------------------------
       
   328 //
       
   329 void CMusEngMceOutSession::AdjustVideoCodecL( CMceVideoCodec& aVideoCodec,
       
   330                                               TMceSourceType aSourceType )
       
   331     {
       
   332     MUS_LOG( "mus: [ENGINE]  -> CMusEngMceOutSession::AdjustVideoCodecL()" )
       
   333     
       
   334     CMusEngMceSession::AdjustVideoCodecL( aVideoCodec, aSourceType );
       
   335     
       
   336     if ( aVideoCodec.SdpName() == KMceSDPNameH263() ||
       
   337          aVideoCodec.SdpName() == KMceSDPNameH2632000() )
       
   338         {
       
   339         User::LeaveIfError( 
       
   340                 aVideoCodec.SetPayloadType( KMusEngPayloadTypeVideoH263 ) );
       
   341         }
       
   342     else if ( aVideoCodec.SdpName() == KMceSDPNameH264() )
       
   343         {
       
   344         User::LeaveIfError(
       
   345                 aVideoCodec.SetPayloadType( KMusEngPayloadTypeVideoAvc ) );
       
   346         }
       
   347     else
       
   348         {
       
   349         // NOP
       
   350         }
       
   351     
       
   352     MUS_LOG( "mus: [ENGINE]  <- CMusEngMceOutSession::AdjustVideoCodecL()" )
       
   353     }
       
   354 
       
   355 // -----------------------------------------------------------------------------
       
   356 // Sets payload type and calls overridden base class version
       
   357 // -----------------------------------------------------------------------------
       
   358 //        
       
   359 void CMusEngMceOutSession::AdjustAudioCodecL( CMceAudioCodec& aAudioCodec )
       
   360     {
       
   361     MUS_LOG( "mus: [ENGINE]  -> CMusEngMceOutSession::AdjustAudioCodecL()" )
       
   362     
       
   363     CMusEngMceSession::AdjustAudioCodecL( aAudioCodec );
       
   364     
       
   365     User::LeaveIfError( aAudioCodec.SetPayloadType( KMusEngPayloadTypeAudio ) );
       
   366     
       
   367     MUS_LOG( "mus: [ENGINE]  <- CMusEngMceOutSession::AdjustAudioCodecL()" )
       
   368     }  
       
   369 
       
   370 // -----------------------------------------------------------------------------
       
   371 //
       
   372 // -----------------------------------------------------------------------------
       
   373 //
       
   374 void CMusEngMceOutSession::ProfileRegistered()
       
   375     {
       
   376     MUS_LOG( "mus: [ENGINE]  -> CMusEngMceOutSession::ProfileRegistered()" )
       
   377     
       
   378     if ( iRegistrationPending )
       
   379         {
       
   380         iDeltaTimer->Remove( iRegistrationEntry );
       
   381         iRegistrationPending = EFalse;
       
   382         
       
   383         
       
   384         HBufC* resolvedRecipient = NULL;
       
   385         TRAPD( error, resolvedRecipient = RemoteAddressL() )
       
   386         if ( error != KErrNone )
       
   387             {
       
   388             InformObserverAboutSessionFailure( error );
       
   389             }
       
   390         else
       
   391             {
       
   392             TRAP( error, DoInviteL( *resolvedRecipient ) )
       
   393             delete resolvedRecipient; 
       
   394             if ( error != KErrNone )
       
   395                 {
       
   396                 InformObserverAboutSessionFailure( error );
       
   397                 }
       
   398             }
       
   399         }
       
   400     
       
   401     MUS_LOG( "mus: [ENGINE]  <- CMusEngMceOutSession::ProfileRegistered()" )
       
   402     }
       
   403 
       
   404 // -----------------------------------------------------------------------------
       
   405 //
       
   406 // -----------------------------------------------------------------------------
       
   407 //
       
   408 TBool CMusEngMceOutSession::IsH264Supported() const
       
   409     {
       
   410     return ( iVideoCodecList && iVideoCodecList->FindF( KMceSDPNameH264() ) >= 0 );
       
   411     }
       
   412 
       
   413 // -----------------------------------------------------------------------------
       
   414 //
       
   415 // -----------------------------------------------------------------------------
       
   416 //
       
   417 void CMusEngMceOutSession::CreateMceSessionStructureL( TBool aForceSdpBandwidth )
       
   418     {
       
   419     MUS_LOG( "mus: [ENGINE]  -> CMusEngMceOutSession::CreateMceSessionStructureL()" )
       
   420 
       
   421     CSIPProfile* profile = iSipProfileHandler->Profile();
       
   422     __ASSERT_ALWAYS( profile != NULL, User::Leave( KErrNotReady ) );
       
   423 
       
   424     // Create session
       
   425     iSession = CMceOutSession::NewL( *iManager, *profile, *iRecipient );
       
   426 
       
   427     // Remove QoS-lines if needed
       
   428     if ( profile->Type().iSIPProfileClass == 
       
   429          TSIPProfileTypeInfo::EInternet ||
       
   430          MultimediaSharingSettings::ForceInternetSignalingSettingL() ==
       
   431          MusSettingsKeys::EForceInternetSignaling ||
       
   432          iOperatorVariant)
       
   433         {
       
   434         iSession->SetModifierL( KMcePreconditions, KMcePreconditionsNotUsed );
       
   435         MUS_LOG( "mus: [ENGINE]     Usage of preconditions denied" )
       
   436         }
       
   437         
       
   438     SetSessionSdpLinesL( *iSession, aForceSdpBandwidth );
       
   439 
       
   440     // Create bundle for local streams
       
   441     
       
   442     CMceStreamBundle* localBundle = 
       
   443                         CMceStreamBundle::NewLC( CMceStreamBundle::ELS );
       
   444 
       
   445     // To complete session structure, let the sibling classes add video out
       
   446     // and possibly needed audio streams
       
   447     CompleteSessionStructureL( *localBundle );
       
   448 
       
   449     // Create stream to display and share source with video outstream
       
   450     CMceVideoStream* streamForDisplay = CMceVideoStream::NewLC();
       
   451 
       
   452     CMceVideoStream* videoOut = MusEngMceUtils::GetVideoOutStreamL( *iSession );
       
   453     
       
   454     SetMediaSdpLinesL( *videoOut, aForceSdpBandwidth );
       
   455 		
       
   456     streamForDisplay->SetSourceL( videoOut->Source() );
       
   457 
       
   458     AddDisplayL( *streamForDisplay );
       
   459 
       
   460     iSession->AddStreamL( streamForDisplay );
       
   461     CleanupStack::Pop( streamForDisplay );    
       
   462 
       
   463     // Check if there are audio streams to bundle with
       
   464     if ( localBundle->Streams().Count() > 0 ) 
       
   465         {
       
   466         localBundle->AddStreamL( *streamForDisplay );
       
   467         iSession->AddBundleL( localBundle );
       
   468         CleanupStack::Pop( localBundle );
       
   469         }
       
   470     else
       
   471         {
       
   472         CleanupStack::PopAndDestroy( localBundle );
       
   473         }
       
   474 
       
   475     MUS_LOG( "mus: [ENGINE]  <- CMusEngMceOutSession::CreateMceSessionStructureL()" )
       
   476     }
       
   477 
       
   478 // -----------------------------------------------------------------------------
       
   479 //
       
   480 // -----------------------------------------------------------------------------
       
   481 //
       
   482 void CMusEngMceOutSession::DoInviteL( const TDesC& aRecipient )
       
   483     {
       
   484     MUS_LOG_TDESC( "mus: [ENGINE]  -> CMusEngMceOutSession::DoInviteL(): ",
       
   485                    aRecipient ) 
       
   486 
       
   487     HBufC* resolvedRecipient = NULL;
       
   488     if ( aRecipient.Length() > 0 )
       
   489         {
       
   490         resolvedRecipient = aRecipient.AllocLC();
       
   491         }
       
   492     else
       
   493         {
       
   494         resolvedRecipient = ResolveRecipientLC();
       
   495         }
       
   496     
       
   497     // delete possibly existing recipient
       
   498     delete iRecipient;
       
   499     iRecipient = NULL;  
       
   500     
       
   501     TMusEngUriParser parser( *resolvedRecipient ); 
       
   502     parser.ParseUriL();    
       
   503     iRecipient = parser.GetUri8L();    
       
   504     
       
   505     /* Set the display name to recipient address if displayname is empty */
       
   506     if ( !iRemoteDisplayName || iRemoteDisplayName->Length() == 0 )
       
   507         {
       
   508         HBufC* tmp = parser.GetUri16L( ETrue );
       
   509         delete iRemoteDisplayName;
       
   510         iRemoteDisplayName = tmp;
       
   511         }
       
   512     
       
   513     CleanupStack::PopAndDestroy( resolvedRecipient );
       
   514     
       
   515     if ( iSession )
       
   516         {
       
   517         MUS_ENG_LOG_SESSION_STATE( *iSession ) 
       
   518         
       
   519         if ( iSession->State() == CMceSession::EIdle ||
       
   520              iSession->State() == CMceSession::ETerminated )
       
   521             {
       
   522             // This is the case when last invite has ended up to an error,
       
   523             // last sharing has ended normally, or construction of the session
       
   524             // stucture has not been completed. Delete old session and try to
       
   525             // continue normally.
       
   526             delete iSession;
       
   527             iSession = NULL;
       
   528             MUS_LOG( "mus: [ENGINE]     Existing session deleted")
       
   529             }
       
   530         else
       
   531             {
       
   532             // Session is already ongoing. Leave.
       
   533             User::Leave( KErrAlreadyExists );
       
   534             }
       
   535       }
       
   536     
       
   537     const TUint KMusEngOneMinuteTimeout = 60000000;
       
   538     if ( iSipProfileHandler->IsRegistered() )
       
   539         {
       
   540         CreateMceSessionStructureL();   
       
   541         EstablishSessionL();
       
   542 	// Start one minute expiration timer
       
   543         TTimeIntervalMicroSeconds32 interval( KMusEngOneMinuteTimeout );
       
   544         iDeltaTimer->Remove( iInvitationResponseEntry );
       
   545         iDeltaTimer->Queue( interval, iInvitationResponseEntry );
       
   546         }
       
   547     else
       
   548         {
       
   549         iRegistrationPending = ETrue;
       
   550         // Start one minute expiration timer
       
   551         TTimeIntervalMicroSeconds32 interval( KMusEngOneMinuteTimeout );
       
   552         iDeltaTimer->Remove( iRegistrationEntry );
       
   553         iDeltaTimer->Queue( interval, iRegistrationEntry );
       
   554         }
       
   555     
       
   556     MUS_LOG( "mus: [ENGINE]  <- CMusEngMceOutSession::DoInviteL()" )
       
   557     }
       
   558 
       
   559 // -----------------------------------------------------------------------------
       
   560 //
       
   561 // -----------------------------------------------------------------------------
       
   562 //
       
   563 HBufC* CMusEngMceOutSession::ResolveRecipientLC()
       
   564     {
       
   565     MUS_LOG( "mus: [ENGINE]  -> CMusEngMceOutSession::ResolveRecipientLC()" )
       
   566     
       
   567     HBufC* resolvedRecipient = NULL;
       
   568     TRAPD( err, 
       
   569         resolvedRecipient = 
       
   570             ReadDescPropertyL( NMusSessionApi::KRemoteSipAddress ) );
       
   571     if ( err != KErrNone )
       
   572         {
       
   573         __ASSERT_ALWAYS( err != KErrNoMemory, User::Leave( KErrNoMemory ) );
       
   574         resolvedRecipient = KNullDesC().AllocL();
       
   575         }
       
   576     CleanupStack::PushL( resolvedRecipient );
       
   577     
       
   578     delete iRemoteSipAddressProposal;
       
   579     iRemoteSipAddressProposal = NULL;
       
   580     TRAP( err, 
       
   581         iRemoteSipAddressProposal = 
       
   582             ReadDescPropertyL( NMusSessionApi::KRemoteSipAddressProposal ) );
       
   583     if ( err != KErrNone )
       
   584         {
       
   585         __ASSERT_ALWAYS( err != KErrNoMemory, User::Leave( KErrNoMemory ) );
       
   586         iRemoteSipAddressProposal = KNullDesC().AllocL();
       
   587         }
       
   588     
       
   589     if ( resolvedRecipient->Length() > 0 )
       
   590         {
       
   591         if ( resolvedRecipient->Find( KMusEngCommaSymbol ) != KErrNotFound )
       
   592             {
       
   593             // Split the addresses using KMusCommaSymbol as a separator
       
   594             CDesCArray* addresses =
       
   595                 new( ELeave )CDesCArrayFlat( KMusEngSipAddressesMaxAmount );
       
   596             CleanupStack::PushL( addresses );
       
   597             SplitL( *resolvedRecipient, KMusEngCommaSymbol, addresses );          
       
   598             
       
   599             // Show List Query Dialog
       
   600             CleanupStack::Pop( addresses );
       
   601             CleanupStack::PopAndDestroy( resolvedRecipient );
       
   602             CleanupStack::PushL( addresses );
       
   603             resolvedRecipient = HBufC::NewLC( KMusEngSipAddressMaxLength );
       
   604             TPtr ptrRetryAddr( resolvedRecipient->Des() ); 
       
   605             if ( !LcUiProviderL().SelectRecipient( *addresses, ptrRetryAddr ) )
       
   606                 {
       
   607                 // Address not selected from provided list
       
   608                 User::Leave( KErrNotFound );
       
   609                 }
       
   610             CleanupStack::Pop( resolvedRecipient );
       
   611             CleanupStack::PopAndDestroy( addresses );
       
   612             CleanupStack::PushL( resolvedRecipient );
       
   613             }
       
   614         }
       
   615     else
       
   616         {
       
   617         __ASSERT_ALWAYS( ++iTriedInvitations < 2, User::Leave( KErrNotFound ) );
       
   618         
       
   619         CleanupStack::PopAndDestroy( resolvedRecipient );
       
   620         resolvedRecipient = NULL;
       
   621         resolvedRecipient = HBufC::NewLC( KMusEngSipAddressMaxLength );
       
   622         __ASSERT_ALWAYS( 
       
   623             iRemoteSipAddressProposal->Length() < KMusEngSipAddressMaxLength,
       
   624             User::Leave( KErrOverflow ) );
       
   625         resolvedRecipient->Des().Copy( *iRemoteSipAddressProposal );
       
   626         TPtr ptrRetryAddr( resolvedRecipient->Des() );
       
   627         InputRecipientL( ptrRetryAddr );
       
   628         iAddressQueried = ETrue;
       
   629         }
       
   630     
       
   631     MUS_LOG( "mus: [ENGINE]  -> CMusEngMceOutSession::ResolveRecipientLC()" )
       
   632     
       
   633     return resolvedRecipient;
       
   634     }
       
   635 
       
   636 // -----------------------------------------------------------------------------
       
   637 //
       
   638 // -----------------------------------------------------------------------------
       
   639 //
       
   640 TInt CMusEngMceOutSession::AsyncBrakeCompleted( TAny* aPtr )
       
   641     {
       
   642     if ( aPtr )
       
   643         {
       
   644         reinterpret_cast<CMusEngMceOutSession*>( aPtr )->HandleRecipientNotFound();
       
   645         }
       
   646     return KErrNone;
       
   647     }
       
   648 
       
   649 // -----------------------------------------------------------------------------
       
   650 //
       
   651 // -----------------------------------------------------------------------------
       
   652 //
       
   653 TInt CMusEngMceOutSession::RegistrationTimerExpired( TAny* aPtr )
       
   654     {
       
   655     if ( aPtr )
       
   656         {
       
   657         CMusEngMceOutSession* session = 
       
   658             reinterpret_cast< CMusEngMceOutSession* >( aPtr );
       
   659         session->InformObserverAboutSessionFailure( KErrGeneral );
       
   660         }
       
   661     return KErrNone;
       
   662     }
       
   663 
       
   664 // -----------------------------------------------------------------------------
       
   665 //
       
   666 // -----------------------------------------------------------------------------
       
   667 //
       
   668 TInt CMusEngMceOutSession::InvitationResponseTimerExpired( TAny* aPtr )
       
   669     {
       
   670     if ( aPtr )
       
   671         {
       
   672         CMusEngMceOutSession* session = 
       
   673             reinterpret_cast< CMusEngMceOutSession* >( aPtr );
       
   674         if ( !session->IgnoreErrorNote() )
       
   675             {
       
   676             session->InformObserverAboutSessionFailure( MLcSession::ENoAnswer );
       
   677             }
       
   678         }
       
   679     return KErrNone;
       
   680     }
       
   681 
       
   682 // -----------------------------------------------------------------------------
       
   683 //
       
   684 // -----------------------------------------------------------------------------
       
   685 //
       
   686 TBool CMusEngMceOutSession::IgnoreErrorNote()
       
   687     {
       
   688     TBool ignore = ETrue;
       
   689     if ( iSession && 
       
   690           ( iSession->State() == CMceSession::EOffering || 
       
   691          iSession->State() == CMceSession::EProceeding ) )
       
   692         {
       
   693         ignore = EFalse;
       
   694         }
       
   695      return ignore;   
       
   696     }
       
   697 
       
   698 // -----------------------------------------------------------------------------
       
   699 //
       
   700 // -----------------------------------------------------------------------------
       
   701 //
       
   702 void CMusEngMceOutSession::InitRecipientNotFoundHandling()
       
   703     {
       
   704     MUS_LOG( "mus: [ENGINE]  -> CMusEngMceOutSession::InitRecipientNotFoundHandling()" )
       
   705     
       
   706     iDeltaTimer->Remove( iAsyncBrakeEntry );
       
   707     const TUint KMusEngAsyncBrakeTimeout = 1;
       
   708     TTimeIntervalMicroSeconds32 interval( KMusEngAsyncBrakeTimeout );
       
   709     iDeltaTimer->Queue( interval, iAsyncBrakeEntry );
       
   710     
       
   711     MUS_LOG( "mus: [ENGINE]  <- CMusEngMceOutSession::InitRecipientNotFoundHandling()" )
       
   712     }
       
   713 
       
   714 // -----------------------------------------------------------------------------
       
   715 //
       
   716 // -----------------------------------------------------------------------------
       
   717 //
       
   718 void CMusEngMceOutSession::HandleRecipientNotFound()
       
   719     {
       
   720     MUS_LOG( "mus: [ENGINE]  -> CMusEngMceOutSession::HandleRecipientNotFound()" )
       
   721     
       
   722     TInt err( KErrNotFound );
       
   723     
       
   724     TBool retry( EFalse );
       
   725     TRAP( err, retry = DoSyncRetryL() );
       
   726     
       
   727     if ( err != KErrNone || !retry )
       
   728         {
       
   729         InformObserverAboutSessionFailure( MLcSession::ERecipientNotFound );
       
   730         }
       
   731     
       
   732     MUS_LOG( "mus: [ENGINE]  <- CMusEngMceOutSession::HandleRecipientNotFound()" )
       
   733     }
       
   734 
       
   735 // -----------------------------------------------------------------------------
       
   736 //
       
   737 // -----------------------------------------------------------------------------
       
   738 //
       
   739 TBool CMusEngMceOutSession::DoSyncRetryL()
       
   740     {
       
   741     __ASSERT_ALWAYS( iRemoteSipAddressProposal, User::Leave( KErrNotFound ) );
       
   742     __ASSERT_ALWAYS( 
       
   743         iRemoteSipAddressProposal->Length() < KMusEngSipAddressMaxLength,
       
   744         User::Leave( KErrOverflow ) );    
       
   745     
       
   746     TBool retry( EFalse );
       
   747     
       
   748     if ( ++iTriedInvitations < 2 )
       
   749         {        
       
   750         TBuf<KMusEngSipAddressMaxLength> retryAddress;
       
   751         retryAddress.Copy( *iRemoteSipAddressProposal );
       
   752         InputRecipientL( retryAddress );
       
   753         DoInviteL( retryAddress );
       
   754 
       
   755         retry = ETrue;
       
   756         iAddressQueried = ETrue;
       
   757         }
       
   758     return retry;
       
   759     }
       
   760 
       
   761 // -----------------------------------------------------------------------------
       
   762 //
       
   763 // -----------------------------------------------------------------------------
       
   764 //
       
   765 void CMusEngMceOutSession::SplitL( const TDesC& aDes,
       
   766                                    const TDesC& aChar,
       
   767                                    CDesCArray* aArray )
       
   768     {
       
   769     TInt charPos( 0 );
       
   770     TPtrC ptr( aDes );
       
   771     TBool found = EFalse;
       
   772     while( ( charPos = ptr.Find( aChar ) ) > 0 )
       
   773         {
       
   774         found = ETrue;
       
   775         TPtrC str = ptr.Left( charPos );
       
   776         aArray->AppendL( str );
       
   777         ptr.Set( ptr.Right( ptr.Length() - str.Length() - 1 ) );
       
   778         }
       
   779     if ( found && ptr.Length() > 0 )
       
   780         {
       
   781         aArray->AppendL( ptr );
       
   782         }
       
   783     }
       
   784 
       
   785 // -----------------------------------------------------------------------------
       
   786 //
       
   787 // -----------------------------------------------------------------------------
       
   788 //
       
   789 HBufC* CMusEngMceOutSession::ReadDescPropertyL( TUint aKey )
       
   790     {
       
   791     MUS_LOG1( "mus: [ENGINE]     -> CMusEngMceOutSession::ReadDescPropertyL: aKey: [%d]",
       
   792                             aKey );
       
   793 
       
   794     TBuf<RProperty::KMaxPropertySize> buffer;
       
   795 
       
   796     User::LeaveIfError( RProperty::Get( NMusSessionApi::KCategoryUid,
       
   797                                         aKey,
       
   798                                         buffer ) );
       
   799     HBufC* desc = buffer.AllocL();
       
   800     MUS_LOG_TDESC( "mus: [ENGINE]    <- CMusEngMceOutSession::ReadDescPropertyL: val: ",
       
   801                             (*desc) );
       
   802     return desc;
       
   803     }
       
   804 
       
   805 // -----------------------------------------------------------------------------
       
   806 //
       
   807 // -----------------------------------------------------------------------------
       
   808 //
       
   809 HBufC* CMusEngMceOutSession::RemoteAddressL() const
       
   810     {
       
   811     MUS_LOG( "mus: [ENGINE]  -> CMusEngMceOutSession::RemoteAddressL()" )
       
   812     
       
   813     __ASSERT_ALWAYS( iRecipient, User::Leave( KErrNotReady ) );
       
   814     
       
   815     HBufC* remoteAddr = HBufC::NewLC( iRecipient->Length() );
       
   816     TPtr ptrRemoteAddr( remoteAddr->Des() );
       
   817     User::LeaveIfError( 
       
   818         CnvUtfConverter::ConvertToUnicodeFromUtf8( 
       
   819             ptrRemoteAddr, *iRecipient ) );
       
   820     
       
   821     MUS_LOG( "mus: [ENGINE]  <- CMusEngMceOutSession::RemoteAddressL()" )
       
   822     
       
   823     CleanupStack::Pop( remoteAddr );
       
   824     return remoteAddr;
       
   825     }
       
   826 
       
   827 // -----------------------------------------------------------------------------
       
   828 // From MLcSession, Should return the displayname of the remote terminal
       
   829 // If found in phone book than contactname else user entered sip address
       
   830 // -----------------------------------------------------------------------------
       
   831 //
       
   832 const TDesC& CMusEngMceOutSession::RemoteDisplayName()
       
   833     {      
       
   834     if ( !iRemoteDisplayName )
       
   835         {
       
   836         return KNullDesC;
       
   837         }
       
   838     return *iRemoteDisplayName;
       
   839     }
       
   840 
       
   841 // -----------------------------------------------------------------------------
       
   842 // Query to the user for sip address of the remote party.
       
   843 // If the user entered a new sip address then reset the displayname 
       
   844 // to user entered sip address.
       
   845 // -----------------------------------------------------------------------------
       
   846 //
       
   847 void CMusEngMceOutSession::InputRecipientL( TDes& aRecipientAddress )
       
   848     {   
       
   849     if ( !LcUiProviderL().InputRecipient( aRecipientAddress ) )
       
   850        {
       
   851        User::Leave( KErrCancel );
       
   852        }    
       
   853     /* displayname is no longer valid since user entered a new sip address
       
   854      * and displayname will be set to sip address when invitation sent.
       
   855      */
       
   856     delete iRemoteDisplayName;
       
   857     iRemoteDisplayName = NULL;
       
   858     }
       
   859 
       
   860 // End of file