callcontinuity/vcc/src/cvccdirector.cpp
changeset 0 a4daefaec16c
child 6 fc8c25e5a2e8
equal deleted inserted replaced
-1:000000000000 0:a4daefaec16c
       
     1 /*
       
     2 * Copyright (c) 2006-2008 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:   Handles all common logic for VCC proxy and handles sessions.
       
    15 *
       
    16 */
       
    17 
       
    18 //cleanup stack operations
       
    19 #include <mccpssobserver.h>
       
    20 #include <spnotifychange.h>
       
    21 #include <spsettings.h>
       
    22 #include <spentry.h>
       
    23 #include <spproperty.h>
       
    24 
       
    25 #include "vcchotrigger.h"
       
    26 #include "cvccdirector.h"
       
    27 #include "cvccconferencecall.h"
       
    28 #include "cvccperformer.h"
       
    29 #include "vccengpspropertylistener.h"
       
    30 #include "vccsubscribekeys.h"
       
    31 #include "vccsettingsreader.h"
       
    32 #include "vccdefinitions.h"
       
    33 #include "rubydebug.h"
       
    34 #include "cvccdtmfprovider.h"
       
    35 
       
    36 // ---------------------------------------------------------------------------
       
    37 // CVccDirector::CVccDirector
       
    38 // ---------------------------------------------------------------------------
       
    39 //
       
    40 CVccDirector::CVccDirector(): 
       
    41 	iImplementationUid( KVCCImplementationUid )
       
    42 	
       
    43     {
       
    44     RUBY_DEBUG_BLOCK( "CVccDirector::CVccDirector" );
       
    45     }
       
    46 
       
    47 // ---------------------------------------------------------------------------
       
    48 // CVccDirector::PointerArrayCleanup
       
    49 // ---------------------------------------------------------------------------
       
    50 //
       
    51 void CVccDirector::PointerArrayCleanup( TAny* aArray )
       
    52     {
       
    53     static_cast<RPointerArray<CConvergedCallProvider>*>( aArray )->ResetAndDestroy();
       
    54     static_cast<RPointerArray<CConvergedCallProvider>*>( aArray )->Close();
       
    55     }
       
    56 
       
    57 // ---------------------------------------------------------------------------
       
    58 // CVccDirector::ConstructL
       
    59 // ---------------------------------------------------------------------------
       
    60 //
       
    61 void CVccDirector::ConstructL()
       
    62     {
       
    63     RUBY_DEBUG_BLOCKL( "CVccDirector::ConstructL" );
       
    64 
       
    65     iSvpLoaded = EFalse;
       
    66     FillCallProviderArrayL();
       
    67     
       
    68     // Create the HO-trigger and connect to the wlan network
       
    69     iHoTrigger = CVccHoTrigger::NewL();
       
    70     
       
    71 	iPropListener = CVccEngPsPropertyListener::NewL( KPSVccPropertyCategory, 
       
    72             KVccPropKeyHoRequest );
       
    73 	RUBY_DEBUG0( "- Called CVccEngPsPropertyListener::NewL" );
       
    74 	iPropListener->AddObserverL( *this );
       
    75 	RUBY_DEBUG0( "- Called iPropListener->AddObserverL" );
       
    76 	iPropListener->Start();
       
    77 	RUBY_DEBUG0( "- Called iPropListener->Start()" );
       
    78 	
       
    79 	//notifies about the changes to SP table
       
    80 	iSpNotifier = CSPNotifyChange::NewL( *this );
       
    81 	//start service provider table notifier
       
    82     StartSpNotifierL();
       
    83     
       
    84 	//link states
       
    85   	iStateInit.LinkState(iStateCalling);
       
    86   	iStateCalling.LinkState(iStateReleasing, iStateInit, iStateFailing );
       
    87   	iStateReleasing.LinkState(iStateInit);
       
    88   	iStateFailing.LinkState( iStateInit );
       
    89   	
       
    90   	iHoKeyValue = KErrNotFound;
       
    91     }
       
    92 
       
    93 // ---------------------------------------------------------------------------
       
    94 // CVccDirector::NewL
       
    95 // ---------------------------------------------------------------------------
       
    96 //
       
    97 CVccDirector* CVccDirector::NewL()
       
    98     {
       
    99     RUBY_DEBUG_BLOCKL( "CVccDirector::NewL" );
       
   100     CVccDirector* self = new ( ELeave ) CVccDirector();
       
   101     CleanupStack::PushL( self );
       
   102     self->ConstructL();
       
   103     CleanupStack::Pop( self );
       
   104     return self;
       
   105     }
       
   106 
       
   107 // ---------------------------------------------------------------------------
       
   108 // CVccDirector::~CVccDirector
       
   109 // ---------------------------------------------------------------------------
       
   110 //
       
   111 CVccDirector::~CVccDirector()
       
   112     {
       
   113     RUBY_DEBUG0( "CVccDirector::~CVccDirector() - ENTER" );
       
   114 
       
   115     delete iConference;
       
   116     iProviders.ResetAndDestroy();
       
   117     iProviders.Close();
       
   118     iPerfArray.ResetAndDestroy();
       
   119     iPerfArray.Close();
       
   120     iInitialisedPlugins.Close();
       
   121     delete iPropListener;
       
   122     
       
   123     if( iSpNotifier )
       
   124     	{
       
   125     	iSpNotifier->Cancel();
       
   126     	}
       
   127    	delete iSpNotifier;
       
   128     
       
   129     delete iHoTrigger;
       
   130     delete iDtmfProvider;
       
   131     REComSession::FinalClose();
       
   132     
       
   133     RUBY_DEBUG0( "CVccDirector::~CVccDirector() - EXIT" );
       
   134     }
       
   135 
       
   136 // ---------------------------------------------------------------------------
       
   137 // CVccDirector::FillCallProviderArrrayL
       
   138 // ---------------------------------------------------------------------------
       
   139 //
       
   140 void CVccDirector::FillCallProviderArrayL()
       
   141 	{
       
   142     //no supplementary services
       
   143     //creating cs and sipvoipproviders
       
   144     
       
   145     //List implementations
       
   146     //Only load cs plugin in the boot. SVP will be loaded when needed.
       
   147     RImplInfoPtrArray implementations;
       
   148     TCleanupItem arrayCleanup( PointerArrayCleanup, &implementations );
       
   149     CleanupStack::PushL( arrayCleanup );
       
   150 
       
   151     CConvergedCallProvider::ListImplementationsL( implementations );
       
   152  
       
   153     for( TInt i = 0; i<implementations.Count(); i++ )
       
   154         {
       
   155         RUBY_DEBUG1( "- for loop counter value: %d", i );
       
   156         CImplementationInformation *info = implementations[i];
       
   157         if ( info->ImplementationUid().iUid == KCSCallProviderPlugId )
       
   158             {
       
   159             CConvergedCallProvider* provider =
       
   160                 CConvergedCallProvider::NewL( info->ImplementationUid() );
       
   161             CleanupStack::PushL( provider );
       
   162            
       
   163             User::LeaveIfError( iProviders.Append( provider ) );
       
   164             
       
   165             CleanupStack::Pop( provider ); //aProvider
       
   166             }
       
   167         }
       
   168     
       
   169     CleanupStack::PopAndDestroy();//implementations
       
   170   
       
   171     TRAP_IGNORE( CheckVoipEnabledL(  VccSettingsReader::VoIPServiceIdL() ) );
       
   172 	}
       
   173 
       
   174 // ---------------------------------------------------------------------------
       
   175 // CVccDirector::IsVccOwnedPlugin
       
   176 // Checks is the given call provider plugin used by VCC 
       
   177 // ---------------------------------------------------------------------------
       
   178 //
       
   179 TBool CVccDirector::IsVccOwnedPlugin( TInt aPluginId )
       
   180 	{
       
   181 	if( aPluginId == KSipVoipCallProviderPlugId || 
       
   182 		aPluginId == KCSCallProviderPlugId	)
       
   183 			return ETrue;
       
   184 	
       
   185 	return EFalse;
       
   186 	}
       
   187 
       
   188 // ---------------------------------------------------------------------------
       
   189 // CVccDirector::InitializeL
       
   190 // Tries to initialize all call provider plugins used by VCC.
       
   191 // ---------------------------------------------------------------------------
       
   192 //
       
   193 void CVccDirector::InitializeL( const MCCPObserver& aMonitor,
       
   194                                   const MCCPSsObserver& aSsObserver )
       
   195     {
       
   196     RUBY_DEBUG_BLOCKL( "CVccDirector::InitializeL" );
       
   197     
       
   198     if ( iProviders.Count() == 0 )
       
   199     	{
       
   200     	User::Leave( KErrNotFound );
       
   201     	}
       
   202 	
       
   203     //MT: setting CVccDirector as observer to plugin
       
   204     Initialize( *this, aSsObserver );
       
   205     
       
   206     // save CCP monitor ; CCCEPluginMCCPObserver
       
   207     const MCCPCSObserver& obs = static_cast<const MCCPCSObserver&>( aMonitor );
       
   208     iCCPObserver = const_cast<MCCPCSObserver*>(&obs);
       
   209 
       
   210     const MCCPSsObserver& ssObs = static_cast<const MCCPSsObserver&>( aSsObserver );
       
   211     iCCPSsObserver = const_cast<MCCPSsObserver*>(&ssObs);
       
   212     
       
   213     }
       
   214 
       
   215 // ---------------------------------------------------------------------------
       
   216 // CVccDirector::InitializeL
       
   217 // Tries to initialize call provider plugins VCC uses. 
       
   218 // Informs if  failure.
       
   219 // ---------------------------------------------------------------------------
       
   220 //
       
   221 TBool CVccDirector::Initialize( const MCCPObserver& aMonitor,
       
   222         const MCCPSsObserver& aSsObserver )
       
   223 	{
       
   224     RUBY_DEBUG_BLOCK( "CVccDirector::Initialize" );
       
   225    
       
   226     TBool initSucceeded = ETrue;
       
   227 	
       
   228 	for ( TInt i = 0; i < iProviders.Count() ; i++)
       
   229         {
       
   230         TUid pluginUid = iProviders[ i ]->Uid();
       
   231         RUBY_DEBUG1( "starting to initialize plugin index= %d", i );
       
   232     	
       
   233         TRAPD( err, InitializeL( aMonitor, aSsObserver, *(iProviders[ i ]) ) );
       
   234         RUBY_DEBUG1( "initialization err = %d", err );
       
   235         switch( err )
       
   236 			{
       
   237 			case KErrNone:
       
   238 				iInitialisedPlugins.Append(  pluginUid.iUid );
       
   239 				//fall-through
       
   240 			case KErrAlreadyExists:
       
   241 				RUBY_DEBUG0( "-- VCC plugin initialization OK" );
       
   242 				break;
       
   243 			default:
       
   244 				RUBY_DEBUG0( "-- VCC plugin initialization FAILED" );
       
   245 				initSucceeded = EFalse;
       
   246 				break;
       
   247 			}
       
   248         }
       
   249 	
       
   250 	RUBY_DEBUG1( "-- VCC plugin nbr of initialized plugins:%d",
       
   251 			iInitialisedPlugins.Count() );
       
   252 	return initSucceeded; 
       
   253     }
       
   254 
       
   255 // ---------------------------------------------------------------------------
       
   256 // CVccDirector::InitializeL
       
   257 // Finds from the VCC settings the service id that should be used with the 
       
   258 // given plugin. Uses the service id to initialize plugin.
       
   259 // ---------------------------------------------------------------------------
       
   260 //
       
   261 void CVccDirector::InitializeL( const MCCPObserver& aMonitor,
       
   262         const MCCPSsObserver& aSsObserver, CConvergedCallProvider& aPlugin )
       
   263 	{
       
   264     RUBY_DEBUG_BLOCKL( "CVccDirector::InitializeL" );
       
   265 	TInt serviceId = VccSettingsReader::ServiceIdL( aPlugin.Uid().iUid );
       
   266 	RUBY_DEBUG1( "Initialize plugin with serviceId = %d", serviceId );	   
       
   267     
       
   268 	User::LeaveIfError( serviceId );
       
   269 	
       
   270 	aPlugin.InitializeL( serviceId, aMonitor, 
       
   271 			aSsObserver );
       
   272 	}
       
   273 
       
   274 // ---------------------------------------------------------------------------
       
   275 // CVccDirector::NewCallL
       
   276 // ---------------------------------------------------------------------------
       
   277 //
       
   278 MCCPCall* CVccDirector::NewCallL(
       
   279                             const CCCPCallParameters& aParameters,
       
   280                             const TDesC& aRecipient,
       
   281                             const MCCPCallObserver& aObserver )
       
   282     {
       
   283     RUBY_DEBUG_BLOCKL( "CVccDirector::NewCallL" );
       
   284 
       
   285     // Check call type and translate it into domain type
       
   286     CVccPerformer* perf;
       
   287     TBool csOriginated = EFalse;
       
   288     if( aParameters.CallType() == CCPCall::ECallTypeCSVoice )
       
   289         {
       
   290         csOriginated = ETrue;
       
   291         iHoTrigger->ReadHoAllowedWhenCsOriginatedSettingL();
       
   292         }
       
   293     
       
   294     perf = CVccPerformer::NewL( iProviders, 
       
   295                                 iStateInit, 
       
   296                                 *iHoTrigger, 
       
   297                                 csOriginated );
       
   298     CleanupStack::PushL( perf );
       
   299     User::LeaveIfError( iPerfArray.Append( perf ) ); 
       
   300     CleanupStack::Pop( perf ); // perf
       
   301     return perf->CreatePrimaryCallL( aParameters, aRecipient, aObserver );
       
   302     }
       
   303 
       
   304 // ---------------------------------------------------------------------------
       
   305 // Releases call
       
   306 // ---------------------------------------------------------------------------
       
   307 //
       
   308 TInt CVccDirector::ReleaseCall( MCCPCall& aCall )
       
   309     {
       
   310     RUBY_DEBUG_BLOCK( "CVccDirector::ReleaseCall" );
       
   311     TInt err = KErrNotFound;
       
   312     //Go through the performer array to see which performer should be deleted.
       
   313     for( TInt i = 0; i < iPerfArray.Count(); i++ )
       
   314     	{
       
   315     	if( iPerfArray[i] == &aCall )
       
   316     		{
       
   317             err = iPerfArray[ i ]->ReleaseCall( aCall ); 
       
   318             iPerfArray[ i ]->ReleaseSecondaryCallLeg();
       
   319             delete iPerfArray[ i ];
       
   320             iPerfArray.Remove( i );
       
   321             iPerfArray.Compress();
       
   322             break;
       
   323     		}
       
   324     	}
       
   325     if( iPerfArray.Count() == 0 )
       
   326         {
       
   327         //make it possible to initiate HOs in new call
       
   328         iHoTrigger->ManualHoCallReleased();
       
   329         iHoTrigger->HoAllowed();
       
   330         iHoTrigger->Stop();
       
   331         }
       
   332     //If iHoKeyValue it means that PropertyChanged function has been visited
       
   333     //i.e. handover should be made. Non-active calls need to be released
       
   334     //before handover can be made.
       
   335     if ( iHoKeyValue >= KErrNone )
       
   336         {
       
   337         TRAP( err, PropertyChangedL( KPSVccPropertyCategory, 
       
   338                             KVccPropKeyHoRequest, 
       
   339                             iHoKeyValue ) );
       
   340         }
       
   341     
       
   342     return err;
       
   343     }
       
   344 
       
   345 // ---------------------------------------------------------------------------
       
   346 // Releases emergency call
       
   347 // ---------------------------------------------------------------------------
       
   348 //
       
   349 TInt CVccDirector::ReleaseEmergencyCall( MCCPEmergencyCall& aCall )
       
   350     {
       
   351     RUBY_DEBUG_BLOCK( "CVccDirector::ReleaseEmergencyCall" );
       
   352     for( TInt i = 0; i < iProviders.Count() ; i++)
       
   353            {
       
   354            TUid pluginUid = iProviders[ i ]->Uid();
       
   355            if (pluginUid.iUid == KCSCallProviderPlugId )
       
   356                {
       
   357                RUBY_DEBUG0( "CS Plugin found" ); 
       
   358                return iProviders[i]->ReleaseEmergencyCall( aCall );
       
   359                }
       
   360            }
       
   361     
       
   362     return KErrNotFound;
       
   363     }
       
   364 
       
   365 // ---------------------------------------------------------------------------
       
   366 // Releases conference call
       
   367 // ---------------------------------------------------------------------------
       
   368 //
       
   369 TInt CVccDirector::ReleaseConferenceCall( MCCPConferenceCall& /*aCall*/ )
       
   370     {
       
   371     RUBY_DEBUG_BLOCK( "CVccDirector::ReleaseConferenceCall" );
       
   372     
       
   373     iConference->ReleaseConference();
       
   374     delete iConference;
       
   375     iConference = NULL;
       
   376     iHoTrigger->HoAllowed();
       
   377     if( iPerfArray.Count() > 0 )
       
   378     	{
       
   379     	for( TInt i = 0; i < iPerfArray.Count(); i++ )
       
   380     		{
       
   381     		iPerfArray[i]->ConferenceEnded();
       
   382     		}
       
   383     	}
       
   384     return KErrNone;
       
   385     }
       
   386 
       
   387 // ---------------------------------------------------------------------------
       
   388 // CVccDirector::Uid
       
   389 // ---------------------------------------------------------------------------
       
   390 //
       
   391 const TUid& CVccDirector::Uid() const
       
   392     {
       
   393     RUBY_DEBUG_BLOCK( "CVccDirector::Uid" );
       
   394     return iImplementationUid;
       
   395     }
       
   396 
       
   397 // from ConvergedCallProvider
       
   398 
       
   399 // ---------------------------------------------------------------------------
       
   400 // CVccDirector::NewEmergencySessionL
       
   401 // ---------------------------------------------------------------------------
       
   402 //
       
   403 MCCPEmergencyCall* CVccDirector::NewEmergencyCallL(
       
   404     const TUint32 aServiceId,
       
   405     const TDesC&  aAddress,
       
   406     const MCCPCallObserver& aObserver )
       
   407     {
       
   408     RUBY_DEBUG_BLOCKL( "CVccDirector::NewEmergencyCallL" );
       
   409     for( TInt i = 0; i < iProviders.Count() ; i++)
       
   410         {
       
   411         TUid pluginUid = iProviders[ i ]->Uid();
       
   412         if (pluginUid.iUid == KCSCallProviderPlugId )
       
   413             {
       
   414             RUBY_DEBUG0( "CS Plugin found" ); 
       
   415             return iProviders[i]->NewEmergencyCallL( aServiceId, aAddress, aObserver );
       
   416             }
       
   417         }
       
   418     return NULL;
       
   419     }
       
   420 
       
   421 // ---------------------------------------------------------------------------
       
   422 // CVccDirector::NewConferenceL
       
   423 // ---------------------------------------------------------------------------
       
   424 //
       
   425 MCCPConferenceCall* CVccDirector::NewConferenceL(
       
   426         const TUint32 aServiceId,
       
   427         const MCCPConferenceCallObserver& aObserver )
       
   428     {
       
   429     RUBY_DEBUG_BLOCKL( "CVccDirector::NewConferenceL" );
       
   430     
       
   431     if ( !iConference )
       
   432         {
       
   433         iConference = CVccConferenceCall::NewL( aServiceId, aObserver, iPerfArray );
       
   434         }
       
   435     else
       
   436         {
       
   437         iConference->AddObserverL( aObserver );
       
   438         }
       
   439 
       
   440     iHoTrigger->HoNotAllowedL();
       
   441     return iConference;
       
   442     }
       
   443 
       
   444 // ---------------------------------------------------------------------------
       
   445 // CVccDirector::Caps
       
   446 // ---------------------------------------------------------------------------
       
   447 //
       
   448 TUint32 CVccDirector::Caps() const
       
   449     {
       
   450     RUBY_DEBUG_BLOCK( "CVccDirector::Caps()" );
       
   451     return 0;
       
   452     }
       
   453 
       
   454 // ---------------------------------------------------------------------------
       
   455 // CVccDirector::DTMFProvider
       
   456 // ---------------------------------------------------------------------------
       
   457 //
       
   458 MCCPDTMFProvider* CVccDirector::DTMFProviderL(
       
   459                                            const MCCPDTMFObserver& aObserver )
       
   460     {
       
   461     RUBY_DEBUG_BLOCKL( "CVccDirector::DTMFProviderL" );
       
   462     if( !iDtmfProvider )
       
   463         {
       
   464         iDtmfProvider = CVccDtmfProvider::NewL( iProviders, aObserver, *this );
       
   465         }
       
   466     return iDtmfProvider; 
       
   467     }
       
   468 
       
   469 
       
   470 // ---------------------------------------------------------------------------
       
   471 // CVccDirector::ExtensionProvider
       
   472 // ---------------------------------------------------------------------------
       
   473 //
       
   474 MCCPExtensionProvider* CVccDirector::ExtensionProviderL(
       
   475                                 const MCCPExtensionObserver& /*aObserver*/ )
       
   476     {
       
   477     RUBY_DEBUG_BLOCKL( "CVccDirector::ExtensionProviderL" );
       
   478     return NULL;
       
   479     }
       
   480 
       
   481 // ---------------------------------------------------------------------------
       
   482 // CVccDirector::AddObserverL
       
   483 // ---------------------------------------------------------------------------
       
   484 //
       
   485 void CVccDirector::AddObserverL( const MCCPDTMFObserver& aObserver )
       
   486     {
       
   487     RUBY_DEBUG_BLOCKL( "CVccDirector::AddObserverL" );
       
   488     if(iDtmfProvider)
       
   489         {
       
   490         iDtmfProvider->AddObserverL(aObserver);
       
   491         }
       
   492     }
       
   493 
       
   494 // ---------------------------------------------------------------------------
       
   495 // CVccDirector::RemoveObserver
       
   496 // ---------------------------------------------------------------------------
       
   497 //
       
   498 TInt CVccDirector::RemoveObserver( const MCCPDTMFObserver& aObserver )
       
   499     {
       
   500     RUBY_DEBUG_BLOCK( "CVccDirector::RemoveObserver" );
       
   501     if(iDtmfProvider)
       
   502         {
       
   503         return iDtmfProvider->RemoveObserver(aObserver);
       
   504         }
       
   505     return KErrNotFound;
       
   506     }
       
   507 
       
   508 // ---------------------------------------------------------------------------
       
   509 // CVccDirector::GetLifeTime
       
   510 // ---------------------------------------------------------------------------
       
   511 //
       
   512 TBool CVccDirector::GetLifeTime( TDes8& aLifeTimeInfo )
       
   513     {
       
   514     for( TInt i = 0; i < iProviders.Count(); i++ )
       
   515         {
       
   516         if( iProviders[ i ]->GetLifeTime( aLifeTimeInfo ) )
       
   517             {
       
   518             return ETrue;
       
   519             }
       
   520         }
       
   521     return EFalse;
       
   522     }
       
   523     
       
   524 // ---------------------------------------------------------------------------
       
   525 // CVccDirector::GetCSInfo
       
   526 // ---------------------------------------------------------------------------
       
   527 //
       
   528 TBool CVccDirector::GetCSInfo( CSInfo& aCSInfo )
       
   529     {
       
   530     RUBY_DEBUG_BLOCK( "CVccDirector::GetCSInfo" );
       
   531     for( TInt i = 0; i < iProviders.Count(); i++ )
       
   532         {
       
   533         if( iProviders[ i ]->GetCSInfo( aCSInfo ) )
       
   534             {
       
   535             return ETrue;
       
   536             }
       
   537         }
       
   538     return EFalse;
       
   539     }
       
   540 
       
   541 // ---------------------------------------------------------------------------
       
   542 // CVccDirector::CPPObserver()
       
   543 // ---------------------------------------------------------------------------
       
   544 //
       
   545 const MCCPCSObserver* CVccDirector::CPPObserver() const
       
   546     {
       
   547     RUBY_DEBUG_BLOCK( "CVccDirector::CPPObserver" );
       
   548     return iCCPObserver;
       
   549     }
       
   550 
       
   551 // ---------------------------------------------------------------------------
       
   552 // CVccDirector::ErrorOccurred
       
   553 // ---------------------------------------------------------------------------
       
   554 //
       
   555 void CVccDirector::ErrorOccurred( const TCCPError /*aError*/ )
       
   556     {
       
   557     RUBY_DEBUG_BLOCK( "CVccDirector::ErrorOccurred" );
       
   558     }
       
   559 
       
   560 // ---------------------------------------------------------------------------
       
   561 // CVccDirector::IncomingCall
       
   562 // Transfer call
       
   563 // ---------------------------------------------------------------------------
       
   564 //
       
   565 void CVccDirector::IncomingCall( MCCPCall* /*aCall*/, MCCPCall& /*aTempCall*/ )
       
   566     {
       
   567     RUBY_DEBUG_BLOCK( "CVccDirector::IncomingCall" );
       
   568     }
       
   569 
       
   570 // ---------------------------------------------------------------------------
       
   571 // CVccDirector::IncomingCall
       
   572 // 
       
   573 // ---------------------------------------------------------------------------
       
   574 //
       
   575 void CVccDirector::IncomingCall( MCCPCall* aCall )
       
   576     {
       
   577     TRAP_IGNORE( IncomingCallL( aCall ) );
       
   578     }
       
   579 
       
   580 // ---------------------------------------------------------------------------
       
   581 // CVccDirector::IncomingCallL
       
   582 // 
       
   583 // ---------------------------------------------------------------------------
       
   584 //
       
   585 void CVccDirector::IncomingCallL( MCCPCall* aCall )
       
   586     {
       
   587     RUBY_DEBUG_BLOCK( "CVccDirector::IncomingCallL" );
       
   588 
       
   589     RUBY_DEBUG1( "CVccDirector::IncomingCallL - array count: %d", iPerfArray.Count() );
       
   590     TBool csOriginated = EFalse;
       
   591     if( aCall->Parameters().CallType() == CCPCall::ECallTypeCSVoice )
       
   592         {
       
   593         csOriginated = ETrue;
       
   594         iHoTrigger->ReadHoAllowedWhenCsOriginatedSettingL();
       
   595         
       
   596         }
       
   597     //Create 1 performer for each call
       
   598     
       
   599     CVccPerformer* perf = CVccPerformer::NewL( iProviders, 
       
   600                                                iStateInit, 
       
   601                                                *iHoTrigger,
       
   602                                                csOriginated );
       
   603     CleanupStack::PushL( perf );
       
   604     User::LeaveIfError( iPerfArray.Append( perf ) );
       
   605 	CleanupStack::Pop( perf ); //perf
       
   606     perf->IncomingCall( aCall );
       
   607  	iCCPObserver->IncomingCall( perf );
       
   608     }
       
   609 
       
   610 // ---------------------------------------------------------------------------
       
   611 // CVccDirector::CallCreated
       
   612 // ---------------------------------------------------------------------------
       
   613 //
       
   614 void CVccDirector::CallCreated( MCCPCall* /*aNewTransferCall*/,
       
   615                               MCCPCall* /*aOriginator*/,
       
   616                               TBool /*aAttented*/ )
       
   617     {
       
   618     RUBY_DEBUG_BLOCK( "CVccDirector::CallCreated" );
       
   619     }
       
   620 
       
   621 // ---------------------------------------------------------------------------
       
   622 // CVccDirector::DataPortName
       
   623 // ---------------------------------------------------------------------------
       
   624 //
       
   625 void CVccDirector::DataPortName( TName& aPortName )
       
   626     {
       
   627     RUBY_DEBUG_BLOCK( "CVccDirector::DataPortName" );
       
   628     iCCPObserver->DataPortName( aPortName );
       
   629     }
       
   630 
       
   631 // -----------------------------------------------------------------------------
       
   632 //  Gets called when PS key is changed
       
   633 // -----------------------------------------------------------------------------
       
   634 //
       
   635 void CVccDirector::PropertyChangedL( const TUid /*aCategoryId*/, 
       
   636                                     const TUint aKeyId,
       
   637                                     const TInt aValue )	
       
   638     {
       
   639     RUBY_DEBUG_BLOCKL( "CVccDirector::PropertyChangedL" );
       
   640     // Go through the performer array to see which call is in active state.
       
   641     // HO is done for the active call. Other calls are dropped.
       
   642     if (aKeyId == KVccPropKeyHoRequest && 
       
   643     	( aValue == EVccManualStartCsToPsHoRequest ||
       
   644     	  aValue == EVccAutomaticStartCsToPsHoRequest ||
       
   645           aValue == EVccManualStartPsToCsHoRequest ||
       
   646           aValue == EVccAutomaticStartPsToCsHoRequest ||
       
   647           aValue == EVccAutomaticStartPsToCsHoRequestIfSingleCall ||
       
   648           aValue == EVccAutomaticStartCsToPsHoRequestIfSingleCall ) )
       
   649 		{
       
   650 			// If manual handover is initiated during active call, automatic 
       
   651 			// handovers are no longer done during the ongoing call
       
   652 			// ==> stopping HoTrigger
       
   653 			if ( aValue == EVccManualStartCsToPsHoRequest || 
       
   654              	aValue == EVccManualStartPsToCsHoRequest )
       
   655 				{
       
   656 				iHoTrigger->ManualHoCallStarted();
       
   657 				}
       
   658 		//Check state of call and handover when possible
       
   659         SwitchL( aValue );
       
   660 		
       
   661 	    }//if
       
   662 		
       
   663 	else if (aKeyId == KVccPropKeyHoStatus)
       
   664 		{
       
   665 		RUBY_DEBUG0( "CVccDirector::PropertyChangedL -- no handover" );
       
   666 		iHoKeyValue = KErrNotFound;	
       
   667 		}//else-if
       
   668 
       
   669     }
       
   670 
       
   671 // -----------------------------------------------------------------------------
       
   672 // Callback function for service settings table observer.
       
   673 // Service provider settings table was changed.  
       
   674 // Only VCC service changes are notified
       
   675 // -----------------------------------------------------------------------------
       
   676 //
       
   677 void CVccDirector::HandleNotifyChange( TServiceId aServiceId )
       
   678     {
       
   679     RUBY_DEBUG_BLOCK( "CVccDirector::HandleNotifyChange" );
       
   680     CheckVoipEnabledL( aServiceId );
       
   681     
       
   682     if( !IsPluginInitialized())
       
   683     	RetryInitialization();
       
   684     }
       
   685 
       
   686 // -----------------------------------------------------------------------------
       
   687 // HandleError event recieved from service provider settings table observer
       
   688 // -----------------------------------------------------------------------------
       
   689 //
       
   690 void CVccDirector::HandleError( TInt /*aError*/ )
       
   691    {
       
   692    RUBY_DEBUG_BLOCK( "CVccDirector::HandleError" );
       
   693    }
       
   694 
       
   695 // -----------------------------------------------------------------------------
       
   696 // Get call type of the call and return it.
       
   697 // -----------------------------------------------------------------------------
       
   698 //
       
   699 TInt CVccDirector::CurrentCallTypeForDTMF()
       
   700     {
       
   701     RUBY_DEBUG_BLOCK( "CVccDirector::CurrentCallTypeForDTMF" );
       
   702     TInt ret = KErrNotFound;
       
   703     
       
   704     for( TInt i = 0; i < iPerfArray.Count(); i++ )
       
   705         {
       
   706         if( iPerfArray[i]->PrimaryCall()->State() == 
       
   707             MCCPCallObserver::ECCPStateDialling ||
       
   708             iPerfArray[i]->PrimaryCall()->State() == 
       
   709             MCCPCallObserver::ECCPStateConnecting ||
       
   710             iPerfArray[i]->PrimaryCall()->State() == 
       
   711             MCCPCallObserver::ECCPStateConnected )
       
   712             {
       
   713             ret = (TInt) iPerfArray[i]->PrimaryCall()->Parameters().CallType();
       
   714             break;
       
   715             }
       
   716         }
       
   717     return ret;
       
   718     }
       
   719 
       
   720 // -----------------------------------------------------------------------------
       
   721 // Get call type of the call and and fetch that call provider and
       
   722 // return it.
       
   723 // -----------------------------------------------------------------------------
       
   724 //
       
   725 CConvergedCallProvider* CVccDirector::GetProvider()
       
   726     {
       
   727     CConvergedCallProvider* ret = NULL;
       
   728     
       
   729     //if no performers in array, all calls have been disconnected
       
   730     //and current call must be emergency call -> return CS provider
       
   731     if( iPerfArray.Count() > 0 )
       
   732         {
       
   733         for( TInt i = 0; i < iPerfArray.Count(); i++ )
       
   734             {
       
   735             if( iPerfArray[i]->PrimaryCall()->State() == 
       
   736                 MCCPCallObserver::ECCPStateDialling ||
       
   737                 iPerfArray[i]->PrimaryCall()->State() == 
       
   738                 MCCPCallObserver::ECCPStateConnecting ||
       
   739                 iPerfArray[i]->PrimaryCall()->State() == 
       
   740                 MCCPCallObserver::ECCPStateConnected )
       
   741                 {
       
   742                 if( iPerfArray[ i ]->PrimaryCall()->Parameters().CallType() == 
       
   743                                                CCPCall::ECallTypePS )
       
   744                     {
       
   745                     ret = &iPerfArray[i]->PsProvider();
       
   746                     break;
       
   747                     }
       
   748                 else
       
   749                     {
       
   750                     ret = &iPerfArray[i]->CsProvider();
       
   751                     break;
       
   752                     }
       
   753                 }
       
   754             }
       
   755         }
       
   756     else
       
   757         {
       
   758         for( TInt i = 0; i < iProviders.Count(); i++ )
       
   759             {
       
   760             TUid pluginUid = iProviders[ i ]->Uid();
       
   761             if( pluginUid.iUid == KCSCallProviderPlugId )
       
   762                 {
       
   763                 ret = iProviders[ i ];
       
   764                 }
       
   765             }
       
   766         }
       
   767     return ret;
       
   768     }
       
   769 
       
   770 // -----------------------------------------------------------------------------
       
   771 //  Checks state of calls and acts accordingly
       
   772 //  Anything else except Waiting or connected - hangup
       
   773 //  Waiting - reject
       
   774 //  Connected - handover
       
   775 // -----------------------------------------------------------------------------
       
   776 //
       
   777 void CVccDirector::SwitchL( const TInt aValue )
       
   778     {
       
   779     RUBY_DEBUG_BLOCKL( "CVccDirector::SwitchL" );
       
   780     //if there is only 1 performer in the array it means that handover can be
       
   781     //made with that performer. If there are more performers it meas that it
       
   782     //is multicall situation and non-active calls need to be released before
       
   783     //handover.
       
   784     //This function is called as many times as there are performers. See 
       
   785     //ReleaseCall!
       
   786     if (iPerfArray.Count() > 1 )
       
   787         {
       
   788         if( aValue == EVccAutomaticStartCsToPsHoRequestIfSingleCall || 
       
   789             aValue == EVccAutomaticStartPsToCsHoRequestIfSingleCall )
       
   790             {
       
   791             return;
       
   792             }
       
   793         //Check that the connected call is capable to make handover (ie. it is
       
   794         //PS call and the direction of HO is PS to CS and vica verse).
       
   795 	    for( TInt i = 0; i < iPerfArray.Count(); i++ )
       
   796 	    	{
       
   797 	    	//call is connected
       
   798 	    	if( iPerfArray[i]->PrimaryCall()->State() == MCCPCallObserver::ECCPStateConnected )
       
   799 	    		{
       
   800 	    		//cs call and the direction is ps to cs. no ho, return
       
   801 	    		if( iPerfArray[i]->PrimaryCall()->Parameters().CallType() ==
       
   802 	    		        CCPCall::ECallTypeCSVoice &&
       
   803 	    		        ( aValue == EVccManualStartPsToCsHoRequest 
       
   804 	    				|| aValue == EVccAutomaticStartPsToCsHoRequest ) )
       
   805 	    			{
       
   806 	    			iHoKeyValue = KErrNotFound;
       
   807 	    			return;
       
   808 	    			}
       
   809 	    		//ps call and the direction is cs to ps. no ho, return
       
   810 	    		else if( iPerfArray[i]->PrimaryCall()->Parameters().CallType() ==
       
   811 	    		        CCPCall::ECallTypePS && 
       
   812 						( aValue == EVccManualStartCsToPsHoRequest 
       
   813 	    				|| aValue == EVccAutomaticStartCsToPsHoRequest ) )
       
   814 	    			{
       
   815 	    			iHoKeyValue = KErrNotFound;
       
   816 	    			return;
       
   817 	    			}
       
   818 	    		}
       
   819 	    	}
       
   820 	    //It is now ok to hangup/reject non-active calls and make handover.
       
   821         for( TInt i = 0; i < iPerfArray.Count(); i++)
       
   822             {
       
   823             if ( (iPerfArray[i]->PrimaryCall()->State() == MCCPCallObserver::ECCPStateRinging) ||
       
   824                   iPerfArray[i]->PrimaryCall()->State() == MCCPCallObserver::ECCPStateConnecting   )
       
   825                 {
       
   826                 RUBY_DEBUG0( "CVccDirector::SwitchL - Reject");
       
   827                 User::LeaveIfError( iPerfArray[i]->Reject() );
       
   828                 iHoKeyValue = aValue;
       
   829                 break;
       
   830                 }
       
   831             
       
   832             else if (iPerfArray[i]->PrimaryCall()->State() != MCCPCallObserver::ECCPStateConnected)
       
   833                 {
       
   834                 RUBY_DEBUG0( "CVccDirector::SwitchL - Hangup");
       
   835                 User::LeaveIfError( iPerfArray[i]->HangUp() );
       
   836                 iHoKeyValue = aValue;
       
   837                 break;
       
   838                 }
       
   839             } //for             
       
   840         } //if
       
   841     else
       
   842         {
       
   843         iPerfArray[0]->SwitchL(aValue);
       
   844         iHoKeyValue = KErrNotFound;
       
   845 
       
   846         }//else
       
   847     }
       
   848 
       
   849 // -----------------------------------------------------------------------------
       
   850 // Checks are the plugins vcc uses initialised
       
   851 // -----------------------------------------------------------------------------
       
   852 //
       
   853 TBool CVccDirector::IsPluginInitialized()
       
   854 	{
       
   855 	RUBY_DEBUG_BLOCK( "CVccDirector::IsPluginInitialized" );
       
   856 	
       
   857 	if( iProviders.Count() == 0 )
       
   858 		return EFalse;
       
   859 		
       
   860 	TBool initialised = ETrue;
       
   861 	for( TInt i = 0; i < iProviders.Count() ; i++)
       
   862 		{
       
   863 		TUid pluginUid = iProviders[ i ]->Uid();
       
   864 		
       
   865 		TInt found = iInitialisedPlugins.Find( pluginUid.iUid );
       
   866 		if( found == KErrNotFound )	
       
   867 			{
       
   868 			initialised = EFalse;
       
   869 			break;
       
   870 			}
       
   871 		}
       
   872 	
       
   873 	RUBY_DEBUG1( "-- IsPluginInitialised:%d", initialised );
       
   874 	return initialised;
       
   875 	}
       
   876 
       
   877 // -----------------------------------------------------------------------------
       
   878 // Starts settings provider table observer.
       
   879 // Director is notified about the change in VCC settings. 
       
   880 // -----------------------------------------------------------------------------
       
   881 //
       
   882 void CVccDirector::StartSpNotifierL()
       
   883 	{
       
   884 	RUBY_DEBUG_BLOCKL( "CVccDirector::StartSpNotifierL" );
       
   885 	__ASSERT_DEBUG(iSpNotifier, User::Leave( KErrNotFound ));
       
   886 	
       
   887 
       
   888 	RIdArray array;
       
   889 	CleanupClosePushL( array );
       
   890 
       
   891 	
       
   892 	iSpNotifier->NotifyChangeL( array );
       
   893 	
       
   894 	CleanupStack::PopAndDestroy( &array );
       
   895 	}
       
   896 
       
   897 // -----------------------------------------------------------------------------
       
   898 // Stops settings provider table observer.
       
   899 // -----------------------------------------------------------------------------
       
   900 //
       
   901 void CVccDirector::StopSpNotifierL()
       
   902 	{
       
   903 	RUBY_DEBUG_BLOCK( "CVccDirector::StopSpNotifierL" );
       
   904 	__ASSERT_DEBUG( iSpNotifier, User::Leave( KErrNotFound ) );
       
   905 	iSpNotifier->NotifyChangeCancel();
       
   906 	}
       
   907 
       
   908 // -----------------------------------------------------------------------------
       
   909 // Tries to initialize the call provider plugins that were not 
       
   910 // initialized the first time because of missing settings.
       
   911 // -----------------------------------------------------------------------------
       
   912 //
       
   913 void CVccDirector::RetryInitialization()
       
   914 	{
       
   915 	RUBY_DEBUG_BLOCK( "CVccDirector::ReTryInitializationL" );
       
   916 	Initialize( *this, *iCCPSsObserver );
       
   917 	}
       
   918 
       
   919 // -----------------------------------------------------------------------------
       
   920 // 
       
   921 // -----------------------------------------------------------------------------
       
   922 //
       
   923 void CVccDirector::MoCallCreated( MCCPCall& aCall )
       
   924     {
       
   925     RUBY_DEBUG_BLOCK( "CVccDirector::MoCallCreated" );
       
   926     
       
   927     RUBY_DEBUG1( "CVccDirector::MoCallCreated - array count: %d", iPerfArray.Count() );
       
   928     TBool csOriginated = EFalse;
       
   929     if( aCall.Parameters().CallType() == CCPCall::ECallTypeCSVoice )
       
   930         {
       
   931         csOriginated = ETrue;
       
   932         iHoTrigger->ReadHoAllowedWhenCsOriginatedSettingL();
       
   933             
       
   934         }
       
   935     //Create 1 performer for each call
       
   936         
       
   937     CVccPerformer* perf = CVccPerformer::NewL( iProviders, 
       
   938                                                iStateInit, 
       
   939                                                *iHoTrigger,
       
   940                                                csOriginated );
       
   941     CleanupStack::PushL( perf );
       
   942     User::LeaveIfError( iPerfArray.Append( perf ) );
       
   943     CleanupStack::Pop( perf ); //perf
       
   944     perf->MoCall( &aCall );
       
   945     iCCPObserver->MoCallCreated( *perf );
       
   946     }
       
   947 
       
   948 // -----------------------------------------------------------------------------
       
   949 // 
       
   950 // -----------------------------------------------------------------------------
       
   951 //
       
   952 void CVccDirector::ConferenceCallCreated( MCCPConferenceCall& aConferenceCall )
       
   953     {
       
   954     RUBY_DEBUG_BLOCK( "CVccDirector::ConferenceCallCreated" );
       
   955     if ( !iConference )
       
   956         {
       
   957         TInt err( KErrNone );
       
   958         TRAP( err, CreateConferenceL( aConferenceCall ) );
       
   959         if( KErrNone == err )
       
   960            {
       
   961            TRAP_IGNORE( iHoTrigger->HoNotAllowedL() );
       
   962            iCCPObserver->ConferenceCallCreated( *iConference );  
       
   963            }
       
   964         else
       
   965            {
       
   966            RUBY_DEBUG1( "CVccDirector::Conference call creation failed - error: %d", err );
       
   967            }
       
   968         }
       
   969     }
       
   970 
       
   971 // -----------------------------------------------------------------------------
       
   972 // CVccDirector::CreateConferenceL
       
   973 //
       
   974 // -----------------------------------------------------------------------------
       
   975 //
       
   976 void CVccDirector::CreateConferenceL( MCCPConferenceCall& aConferenceCall )
       
   977     {
       
   978     RUBY_DEBUG_BLOCK( "CVccDirector::CreateConferenceL" );
       
   979     iConference = CVccConferenceCall::NewL( aConferenceCall, iPerfArray );
       
   980     aConferenceCall.AddObserverL( *iConference );
       
   981     }
       
   982 
       
   983 // -----------------------------------------------------------------------------
       
   984 // CVccDirector::CheckVoipEnabledL
       
   985 // -----------------------------------------------------------------------------
       
   986 //
       
   987 void CVccDirector::CheckVoipEnabledL( TServiceId aServiceId )
       
   988     {
       
   989     RUBY_DEBUG_BLOCK( "CVccDirector::CheckVoipEnabledL" );
       
   990     
       
   991     TInt vccService = VccSettingsReader::VccServiceIdL();
       
   992     TInt voipService = 0;
       
   993     if( vccService )
       
   994         {
       
   995         voipService = VccSettingsReader::VoIPServiceIdL();
       
   996         }
       
   997     if( voipService == aServiceId )
       
   998         {
       
   999         RUBY_DEBUG0( "CVccDirector::HandleNotifyChange -- VoIP Service" );
       
  1000         CSPProperty* property = CSPProperty::NewLC();
       
  1001         CSPSettings* settings = CSPSettings::NewLC();
       
  1002         settings->FindPropertyL( aServiceId,
       
  1003                     ESubPropertyVoIPEnabled, *property );
       
  1004             
       
  1005         TOnOff enabled( EOONotSet );
       
  1006         property->GetValue( enabled );
       
  1007             
       
  1008         CleanupStack::PopAndDestroy( settings );
       
  1009         CleanupStack::PopAndDestroy( property );
       
  1010         //if voip is enabled load also SVP and put it into providers array
       
  1011         if( enabled && !iSvpLoaded )
       
  1012             {
       
  1013             RUBY_DEBUG0( "CVccDirector::HandleNotifyChange -- VoIP enabled, load SVP" );
       
  1014             RImplInfoPtrArray implementations;
       
  1015             TCleanupItem arrayCleanup( PointerArrayCleanup, &implementations );
       
  1016             CleanupStack::PushL( arrayCleanup );
       
  1017 
       
  1018             CConvergedCallProvider::ListImplementationsL( implementations );
       
  1019                  
       
  1020             for( TInt i = 0; i < implementations.Count(); i++ )
       
  1021                 {
       
  1022                 RUBY_DEBUG1( "- for loop counter value: %d", i );
       
  1023                 CImplementationInformation *info = implementations[i];
       
  1024                 if( info->ImplementationUid().iUid == KSipVoipCallProviderPlugId )
       
  1025                     {
       
  1026                     CConvergedCallProvider* provider =
       
  1027                          CConvergedCallProvider::NewL( info->ImplementationUid() );
       
  1028                     CleanupStack::PushL( provider );
       
  1029                            
       
  1030                     User::LeaveIfError( iProviders.Append( provider ) );
       
  1031                             
       
  1032                     CleanupStack::Pop( provider );  //provider
       
  1033                         
       
  1034                     if( iDtmfProvider )
       
  1035                         {
       
  1036                         provider->DTMFProviderL( *iDtmfProvider );
       
  1037                         }
       
  1038                     }
       
  1039                 }
       
  1040                 iSvpLoaded = ETrue;
       
  1041                 CleanupStack::PopAndDestroy();  //implementations
       
  1042             }
       
  1043             //if voip is disabled, destroy SVP and remove it from providers array.
       
  1044         else if( !enabled )
       
  1045             {
       
  1046             RUBY_DEBUG0( "CVccDirector::HandleNotifyChange -- VoIP disabled, destroy SVP" );
       
  1047                             
       
  1048             for( TInt i = 0; i < iProviders.Count(); i++ )
       
  1049                 {
       
  1050                 if( iProviders[ i ]->Uid().iUid == KSipVoipCallProviderPlugId )
       
  1051                     {
       
  1052                     delete iProviders[ i ];
       
  1053                     iProviders.Remove( i );
       
  1054                     iProviders.Compress();
       
  1055                     for( TInt a = 0; a < iInitialisedPlugins.Count(); a++ )
       
  1056                         {
       
  1057                         if( iInitialisedPlugins[ a ] == KSipVoipCallProviderPlugId )
       
  1058                             {
       
  1059                             iInitialisedPlugins.Remove( a );
       
  1060                             iInitialisedPlugins.Compress();
       
  1061                             }
       
  1062                         }
       
  1063                     iSvpLoaded = EFalse;
       
  1064                     }
       
  1065                 }
       
  1066             }
       
  1067         }
       
  1068     }