vtengines/vtmediatorplugin/src/cvtmediatorplugin.cpp
changeset 0 ed9695c8bcbe
child 3 b1602a5ab0a3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vtengines/vtmediatorplugin/src/cvtmediatorplugin.cpp	Mon Nov 23 14:47:47 2009 +0200
@@ -0,0 +1,1024 @@
+/*
+* Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:  Video Telephony mediator plugin header
+*
+*/
+
+
+// INCLUDE FILES
+#include <e32def.h>
+#include <w32std.h>
+#include <apacmdln.h>
+#include <apaflrec.h>
+#include <apgcli.h>
+#include <mediatordomainuids.h>
+#include <eikdll.h>
+#include <apgcli.h>
+#include <apgwgnam.h>
+#include <apgtask.h>
+#include <mediatorcommandstotelephonyapi.h>
+#include <videotelcontrolmediatorapi.h>
+#include <videoteltophonecommandsapi.h>
+#include "cvtmediatorplugin.h"
+
+
+// CONSTANTS
+#ifdef _DEBUG
+#define TRACE(x) RDebug::Print( _L(x) );
+#define TRACE2(x,y) RDebug::Print( _L(x),y );
+#else
+#define TRACE(x)
+#define TRACE2(x,y)
+#endif
+                       
+// This array's values are used in algorithm defining if video telephone
+// application should be started. Previous state value is substracted from new 
+// state value and if result is greater than zero, app is started.
+// This tackles transitions where a state is for some reason skipped,
+// e.g. idle -> connected (dialling/ringing/answering states were not detected).
+// Negative value indicates call clearing.
+static const TInt KVtCallStateActionArray[] = {
+    0, //ECallStateUnknown
+    0, //ECallStateIdle
+    1, // ECallStateDialling
+    0, // ECallStateEmergencyDialling (not valid video call state)
+    1, // ECallStateRinging
+    1, // ECallStateConnecting
+    1, // ECallStateConnected
+    0, // ECallStateHangingUp
+    0, // ECallStateHeld (not valid video call state)
+    1, // ECallStateAnswering
+    0, // ECallStateRejecting
+    0  // ECallStateDisconnecting
+    };
+
+static const TInt KVtAppNotReady = 5000;
+
+static const TInt KVtEngMdtrCmdTimeout = 500000;
+
+static const TInt KVtInitCallId = -1000;
+
+// array granularity is 2 (use dataport, release dataport commands)
+static const TInt KVtMdtrCmdArrayGranularity = 2;
+
+const TUid KVtCmVideoTelUiUid = { 0x101F8681 };
+
+static const TInt KRamNeededForVideoCalls = 4000000;
+
+// VT application path 
+_LIT( KVtCmVideoTelUiPath, "\\sys\\bin\\videotelui.exe" );
+
+
+// -----------------------------------------------------------------------------
+// CMediatorTestPlugin::CMediatorTestPlugin
+// First phase construction.
+// -----------------------------------------------------------------------------
+CVtMediatorPlugin::CVtMediatorPlugin() : CMediatorPluginBase(),
+    iCommandList( KVtMdtrCmdArrayGranularity ),
+    iState( EWaitingAppLaunch ),
+    iActiveVideoCallState( ECallStateUnknown ),
+    iWaitingVideoCallState( ECallStateUnknown )
+    
+	{
+	ClearData(iActiveVideoCallInfo, iActiveVideoCallState);
+	ClearData(iWaitingVideoCallInfo, iWaitingVideoCallState);
+	}
+	
+CMediatorPluginBase* CVtMediatorPlugin::NewL()
+    {
+    TRACE("CVtMediatorPlugin::NewL<")
+    CVtMediatorPlugin* self = new (ELeave) CVtMediatorPlugin;
+    TRACE("CVtMediatorPlugin::NewL>")
+    return self;
+    }
+
+// -----------------------------------------------------------------------------
+// Destructor.
+// -----------------------------------------------------------------------------
+CVtMediatorPlugin::~CVtMediatorPlugin()
+	{
+	TRACE("CVtMediatorPlugin::~CVtMediatorPlugin<")
+    
+	if ( iMediatorNotifications )
+	    {
+	    iMediatorNotifications->UnregisterNotificationObserver();
+	    delete iMediatorNotifications;
+	    }
+
+	// ignore error
+	if ( iEventConsumer )
+	    {
+	    iEventConsumer->UnsubscribeEvent(
+	            KMediatorTelephonyDomain,
+	            KCatEventsFromTelephony,
+	            EPhoneEventCallData );     
+	    delete iEventConsumer;
+	    }
+        
+    // ignore error     
+	if ( iEventProvider )
+	    {
+	    iEventProvider->UnregisterEvent(
+	            KMediatorVideoTelephonyDomain,
+	            KCatVideotelInternalEvents,
+	            EVtMediatorEventVideoCallInformation );   
+	    delete iEventProvider;
+	    }
+        
+    // ignore error
+	if ( iCommandResponder )
+	    {
+	    iCommandResponder->UnregisterCommand(
+	                KMediatorVideoTelephonyDomain,
+	                KCatPhoneToVideotelCommands,
+	                iCommandList );
+	    iCommandList.Close();
+	    delete iCommandResponder;
+	    }
+	
+	delete iCommandInitiator;
+    
+           
+    if( iAppDeathActive )
+        {
+        delete iAppDeathActive;
+        iAppThread.Close();
+        iWsSession.Close();
+        
+        }
+
+    TRACE("CVtMediatorPlugin::~CVtMediatorPlugin>")
+	}
+
+// -----------------------------------------------------------------------------
+// StartL.
+// -----------------------------------------------------------------------------
+void CVtMediatorPlugin::StartL()
+	{
+    TRACE("CVtMediatorPlugin.StartL<")
+    
+    // for monitoring VT app starting
+    iMediatorNotifications = CMediatorNotifications::NewL();
+    iMediatorNotifications->RegisterNotificationObserver( this );
+    
+    // consumer for call data events
+    iEventConsumer = CMediatorEventConsumer::NewL( this );
+    
+    iCommandInitiator = CMediatorCommandInitiator::NewL( this );
+    
+    
+    RegisterVtInternalEventL();
+    
+    RegisterDataportCommandL();       
+          
+    TRACE("CVtMediatorPlugin.StartL>")
+	}
+
+// -----------------------------------------------------------------------------
+// MediatorEventL.
+// -----------------------------------------------------------------------------
+void CVtMediatorPlugin::MediatorEventL( TUid /*aDomain*/,
+                             TUid aCategory,
+                             TInt aEventId,
+                             const TDesC8& aData )
+    {
+    TRACE("CVtMediatorPlugin.MediatorEventL<")
+    if ( aCategory == KCatEventsFromTelephony &&
+         aEventId == EPhoneEventCallData )
+        {
+        TTelephonyCallDataParamPackage pckg;
+        pckg.Copy( aData );
+        const TTelephonyCallDataParam telCallData = pckg();        
+        HandleCallStateChangeL( telCallData );        
+        }
+    TRACE("CVtMediatorPlugin.MediatorEventL>")
+    }
+// -----------------------------------------------------------------------------
+// CVtMediatorPlugin::MediatorEventsAddedL
+//
+// subscribes to CLI event when it is registered
+// -----------------------------------------------------------------------------
+//
+void CVtMediatorPlugin::MediatorEventsAddedL( TUid aDomain/*aDomain*/,
+                                   TUid aCategory,
+                                   const REventList& aEvents )
+    {
+    TRACE("CVtMediatorPlugin.MediatorEventsAddedL<")
+    
+    if ( aCategory == KCatEventsFromTelephony )
+        {
+        ChangeCallDataEventSubscriptionL( aEvents, ETrue );
+        }    
+    TRACE("CVtMediatorPlugin.MediatorEventsAddedL>")
+    }
+
+// -----------------------------------------------------------------------------
+// ?classname::?member_function
+//
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CVtMediatorPlugin::MediatorCommandsAddedL( TUid /*aDomain*/,
+                                     TUid aCategory,
+                                     const RCommandList& /*aCommands*/ )
+    {
+    TRACE("CVtMediatorPlugin.MediatorCommandsAddedL<")
+    if ( aCategory == KCatPhoneToVideotelCommands )
+        {
+        HandleVtCommandRegistrationL();
+        }
+    TRACE("CVtMediatorPlugin.MediatorCommandsAddedL>")
+    }
+
+// -----------------------------------------------------------------------------
+// ?classname::?member_function
+//
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CVtMediatorPlugin::MediatorCategoryRemovedL( TUid /*aDomain*/,
+    TUid /*aCategory*/ )
+    {
+    }
+
+// -----------------------------------------------------------------------------
+// ?classname::?member_function
+//
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CVtMediatorPlugin::MediatorEventsRemovedL( TUid /*aDomain*/,
+                                     TUid aCategory,
+                                     const REventList& aEvents )
+    {
+    TRACE("CVtMediatorPlugin.MediatorEventsRemovedL<")
+    if ( aCategory == KCatEventsFromTelephony )
+        {
+        ChangeCallDataEventSubscriptionL( aEvents, EFalse );
+        }    
+    TRACE("CVtMediatorPlugin.MediatorEventsRemovedL>")
+    }
+
+// -----------------------------------------------------------------------------
+// ?classname::?member_function
+//
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CVtMediatorPlugin::MediatorCommandsRemovedL( TUid /*aDomain*/,
+                                       TUid aCategory,
+                                       const RCommandList& /*aCommands*/ )
+    {
+    TRACE("CVtMediatorPlugin.MediatorCommandsRemovedL<")  
+    if ( aCategory == KCatPhoneToVideotelCommands )
+        {
+        // VT has unregistered commands, meaning it is shutting down
+        HandleVtCommandUnregistrationL();
+        }
+    TRACE("CVtMediatorPlugin.MediatorCommandsRemovedL>")
+    }
+
+// -----------------------------------------------------------------------------
+// CVtMediatorPlugin::MediatorCommandL
+//
+// 
+// -----------------------------------------------------------------------------
+//
+void CVtMediatorPlugin::MediatorCommandL( TUid aDomain,
+                                 TUid aCategory, 
+                                 TInt aCommandId,
+                                 TVersion /*aVersion*/, 
+                                 const TDesC8& aData )
+    {
+    TRACE("CVtMediatorPlugin.MediatorCommandL<") 
+    if ( aCategory == KCatPhoneToVideotelCommands )
+        {
+        if ( aCommandId == EVtCmdUseDataport )
+            {
+#ifdef _DEBUG           
+            // error in responding is ignored but printed on debug build
+            const TInt err =
+#endif            
+            iCommandResponder->IssueResponse( 
+                aDomain, aCategory, aCommandId, KErrNone, KNullDesC8() );
+            TRACE2("CVtMediatorPlugin.MediatorCommandL EVtCmdUseDataport err=%d", err )
+            HandleDataportCommandL( aData );
+            }
+        else if ( aCommandId == EVtCmdReleaseDataport )
+            {
+            if ( EReady == iState )
+                {
+                const TVersion version( 
+                        KVideotelMdtrCommandsVersionMajor,
+                        KVideotelMdtrCommandsVersionMinor,
+                        KVideotelMdtrCommandsVersionBuild );
+
+#ifdef _DEBUG           
+            // error in responding is ignored but printed on debug build
+            const TInt err =
+#endif                          
+                iCommandInitiator->IssueCommand(
+                        KMediatorVideoTelephonyDomain,
+                        KCatVideotelInternalCommands,
+                        EVtMediatorReleaseDataport,
+                        version,
+                        KNullDesC8() );
+            TRACE2("CVtMediatorPlugin.MediatorCommandL EVtCmdReleaseDataport, send to VT err=%d", err )
+                
+                }
+            else
+                {
+#ifdef _DEBUG           
+                // error in responding is ignored but printed on debug build
+                const TInt err =
+#endif            
+                iCommandResponder->IssueResponse( 
+                        aDomain, 
+                        aCategory, 
+                        aCommandId, 
+                        KErrNone, 
+                        KNullDesC8() );
+                TRACE2("CVtMediatorPlugin.MediatorCommandL EVtCmdReleaseDataport, just Resp err=%d", err ) 
+                }
+           
+            }
+        }
+    TRACE("CVtMediatorPlugin.MediatorCommandL>")
+    }
+
+// -----------------------------------------------------------------------------
+// CVtMediatorPlugin::CommandResponseL
+//
+// 
+// -----------------------------------------------------------------------------
+//
+void CVtMediatorPlugin::CommandResponseL( TUid aDomain, TUid aCategory, 
+    TInt aCommandId, TInt /*aStatus*/, const TDesC8& /*aData*/ )
+    {
+    TRACE("CVtMediatorPlugin.CommandResponseL<")
+    if( ( aDomain == KMediatorVideoTelephonyDomain ) &&
+        ( aCategory == KCatVideotelInternalCommands ) )
+        {
+        TInt res =
+        iCommandResponder->IssueResponse( 
+                KMediatorVideoTelephonyDomain,
+                KCatPhoneToVideotelCommands,
+                EVtCmdReleaseDataport, 
+                KErrNone, 
+                KNullDesC8() );         
+         TRACE2("CVtMediatorPlugin.CommandResponseL, IssueResponse res: %d", res )  
+         User::LeaveIfError( res );      
+        }
+    TRACE("CVtMediatorPlugin.CommandResponseL>")
+    }
+
+// -----------------------------------------------------------------------------
+// CVtMediatorPlugin::CancelMediatorCommand
+//
+// no-op
+// -----------------------------------------------------------------------------
+//
+void CVtMediatorPlugin::CancelMediatorCommand( TUid /*aDomain*/,
+                                      TUid /*aCategory*/, 
+                                      TInt /*aCommandId*/ )
+    {
+    }
+// -----------------------------------------------------------------------------
+// CVtMediatorPlugin::ChangeCallDataEventSubscriptionL
+//
+// Takes care of 'call data' event subscription.
+// -----------------------------------------------------------------------------
+//
+void CVtMediatorPlugin::ChangeCallDataEventSubscriptionL(
+    const REventList& aEvents,
+    const TBool aEventRegistered )
+    {
+    TRACE("CVtMediatorPlugin.ChangeCLIEventSubscription<")
+   
+    TInt res( KErrNone );
+    TInt eventCount = aEvents.Count();
+    while ( eventCount-- )
+        {
+        const TEvent& aEvent = aEvents[ eventCount ];
+        if ( aEvent.iEventId == EPhoneEventCallData )
+            {
+            if ( aEventRegistered )
+                {
+                // Phone has registered Call data event => subscribe it                
+                const TVersion version(
+                    KTelephonyEventsVersionMajor,
+                    KTelephonyEventsVersionMinor,
+                    KTelephonyEventsVersionBuild );
+                res = iEventConsumer->SubscribeEvent(
+                    KMediatorTelephonyDomain,
+                    KCatEventsFromTelephony,
+                    EPhoneEventCallData, version );
+                }
+            else
+                {
+                // Phone has unregistered Call data event => unsubscribe it
+                res = iEventConsumer->UnsubscribeEvent(
+                    KMediatorTelephonyDomain,
+                    KCatEventsFromTelephony,
+                    EPhoneEventCallData );
+                }
+            TRACE2("   (un)subscribe result=%d", res )
+            eventCount = 0; // break loop
+            }
+        }
+    
+    TRACE2("CVtMediatorPlugin.ChangeCLIEventSubscription result=%d>", res )
+    User::LeaveIfError( res );
+    }
+    
+// -----------------------------------------------------------------------------
+// CVtMediatorPlugin::HandleVtCommandRegistrationL
+//
+// 
+// -----------------------------------------------------------------------------
+//
+void CVtMediatorPlugin::HandleVtCommandRegistrationL()
+    {
+    TRACE("CVtMediatorPlugin.HandleVtCommandRegistrationL<" )
+    if ( iState == EWaitingEventRegistration )
+        {
+        // VT app registered commands => it can also receive events
+        // NOTE: it is expected that VT application first subscribes
+        // to internal events and only after that registers commands to
+        // avoid timing problems.
+        iState = EReady;
+        delete iCallBack;
+        iCallBack = NULL;
+        TCallBack cb( &EventRaiserCallback, this );
+        iCallBack = new ( ELeave ) CAsyncCallBack( cb, 
+            CActive::EPriorityStandard );        
+        TRACE("CVtMediatorPlugin enque async callback" )
+        iCallBack->CallBack();        
+        }
+    TRACE("CVtMediatorPlugin.HandleVtCommandRegistrationL>" )
+    }
+
+TInt CVtMediatorPlugin::EventRaiserCallback( TAny* aAny )
+    {
+    TRACE("CVtMediatorPlugin.EventRaiserCallback<" )
+    CVtMediatorPlugin* plugin = reinterpret_cast<CVtMediatorPlugin*>( aAny );
+    delete plugin->iCallBack;
+    plugin->iCallBack = NULL;
+    TRAP_IGNORE( plugin->RaiseVtEventL() );
+    TRACE("CVtMediatorPlugin.EventRaiserCallback>" )
+    return KErrNone;
+    }
+
+// -----------------------------------------------------------------------------
+// CVtMediatorPlugin::
+//
+// 
+// -----------------------------------------------------------------------------
+//
+void CVtMediatorPlugin::HandleVtCommandUnregistrationL()
+    {
+    // unregistration means that VT app is shutting down.    
+    TRACE("CVtMediatorPlugin.HandleVtCommandUnregistrationL<" )
+    ClearData(iActiveVideoCallInfo, iActiveVideoCallState);
+    //ClearData(iWaitingVideoCallInfo);
+    TRACE("CVtMediatorPlugin.HandleVtCommandUnregistrationL>" )
+    }
+
+
+// -----------------------------------------------------------------------------
+// CVtMediatorPlugin::
+//
+// 
+// -----------------------------------------------------------------------------
+//
+void CVtMediatorPlugin::LaunchVtAppL()
+    {
+        
+    TRACE("CVtMediatorPlugin.LaunchVtAppL<" )
+    
+    if ( !IsEnoughMemory() )
+        {
+        const TVersion KTelephonyCmdVersion(
+                KTelephonyCommandsVersionMajor,
+                KTelephonyCommandsVersionMinor,
+                KTelephonyCommandsVersionBuild );
+        const TInt res =
+        iCommandInitiator->IssueCommand(
+                KMediatorTelephonyDomain,
+                KCatVideoTelToPhoneCommands,
+                EVtCmdLowMemory,
+                KTelephonyCmdVersion,
+                KNullDesC8() );
+        ClearData(iActiveVideoCallInfo, iActiveVideoCallState);
+        ClearData(iWaitingVideoCallInfo, iWaitingVideoCallState);
+        TRACE("CVtMediatorPlugin.LaunchVtAppL, Insufficient Memory" )
+        return;
+        }
+
+    iAppDeathActive = new ( ELeave ) CAppDeathActive( *this, iAppThread );
+       
+    User::LeaveIfError( iWsSession.Connect() );
+
+    TInt wgId = 0;
+    TBool found = EFalse;
+
+    // Check if there is already application running. Then we do not 
+    // start new one - rather we just monitor the existing one.
+    while ( ( wgId != KErrNotFound ) && !found )
+        {
+        CApaWindowGroupName::FindByAppUid( 
+            KVtCmVideoTelUiUid, 
+            iWsSession, 
+            wgId );
+
+        TApaTask task( iWsSession );
+        task.SetWgId( wgId );
+        if ( task.Exists() )
+            {
+            if ( iAppThread.Open( task.ThreadId() ) == KErrNone )
+                {
+                TExitType exitType = iAppThread.ExitType();
+                found = ( exitType == EExitPending );
+
+                if ( found )
+                    {
+                    iAppThreadId = task.ThreadId();
+                    }
+                }
+            }
+            
+        if ( !found )
+            {
+            iAppThread.Close();
+             }
+        }
+
+    // If application was not found, then launch new application.
+    if ( !found )
+        {
+        TThreadId threadId;
+#ifndef SYMBIAN_SUPPORT_UI_FRAMEWORKS_V1
+        CApaCommandLine* cmd = CApaCommandLine::NewLC();
+        cmd->SetExecutableNameL( KVtCmVideoTelUiPath );
+#else // !SYMBIAN_SUPPORT_UI_FRAMEWORKS_V1
+        CApaCommandLine* cmd = CApaCommandLine::NewLC( KVtCmVideoTelUiPath );
+#endif // SYMBIAN_SUPPORT_UI_FRAMEWORKS_V1
+        cmd->SetCommandL( EApaCommandBackground );
+            
+        RApaLsSession session;
+        User::LeaveIfError( session.Connect() );
+        CleanupClosePushL( session );
+            
+        TInt err = session.StartApp( *cmd, threadId );
+        if ( err > KErrNone )
+            {
+            err = KErrGeneral;
+            }
+        User::LeaveIfError( err );
+        CleanupStack::PopAndDestroy( 2, cmd ); // CleanupClosePushL, cmd
+        User::LeaveIfError( iAppThread.Open( threadId ) );
+        iAppThreadId = threadId;
+        }
+
+    // Start active objects.
+    iState = EWaitingEventRegistration;
+    iAppDeathActive->Start();
+    TRACE("CVtMediatorPlugin.LaunchVtAppL>" )
+    }
+
+
+// -----------------------------------------------------------------------------
+// CVtMediatorPlugin::
+//
+// 
+// -----------------------------------------------------------------------------
+//
+void CVtMediatorPlugin::SaveCallData( const TTelephonyCallDataParam& aData, TVtVideoTelephonyCallInformation& iVtCallInfo )
+    {
+    TRACE("CVtMediatorPlugin.SaveCallData<" )
+    iVtCallInfo.iDisplayText = aData.iCLIText.Left(
+        TVtVideoTelephonyCallInformation::TDisplayTextMaxLength );
+        
+    TRACE2("CVtMediatorPlugin.SaveCallData iDisplayText=%S",
+        &iVtCallInfo.iDisplayText );
+                
+    iVtCallInfo.iCallId = aData.iCallId;
+    
+    if ( KNullDesC() != aData.iRemotePhoneNumber )
+        {
+        iVtCallInfo.iVoiceCallPossible = ETrue;
+        }
+    iVtCallInfo.iEventDataValidity |= 
+        TVtVideoTelephonyCallInformation::EDisplayTextValid;
+    TRACE2("CVtMediatorPlugin.SaveCallData data saved=%d>",
+        aData.iCallType == ECallTypeVideo )
+    }
+
+                     
+// -----------------------------------------------------------------------------
+// CVtMediatorPlugin::
+//
+// 
+// -----------------------------------------------------------------------------
+//
+void CVtMediatorPlugin::HandleDataportCommandL( const TDesC8& aData )
+    {
+    TRACE("CVtMediatorPlugin.HandleDataportCommandL<" ) 
+    TDataPortPackage pckg;
+    pckg.Copy( aData );
+    iActiveVideoCallInfo.iDataport = pckg();
+    iActiveVideoCallInfo.iEventDataValidity |= 
+        TVtVideoTelephonyCallInformation::EDataportValid;     
+    RaiseVtEventL();
+    TRACE("CVtMediatorPlugin.HandleDataportCommandL>" )
+    }
+
+                         
+// -----------------------------------------------------------------------------
+// CVtMediatorPlugin::ClearData
+//
+// 
+// -----------------------------------------------------------------------------
+//
+void CVtMediatorPlugin::ClearData(TVtVideoTelephonyCallInformation& aVtCallInfo, TCallState& aCallState)
+    {
+    TRACE("CVtMediatorPlugin.ClearData<" )
+    if ( aVtCallInfo.iCallId == iActiveVideoCallInfo.iCallId )
+        {
+        iState = EWaitingAppLaunch;
+        }
+    aVtCallInfo.iEventDataValidity = 0;
+    aVtCallInfo.iDataport.Zero();
+    aVtCallInfo.iVoiceCallPossible = EFalse;
+    //for video call, it should be 9/10
+    //for other call, it will be from -1 to 8
+    aVtCallInfo.iCallId = KVtInitCallId;
+    aVtCallInfo.iDisplayText.Zero();
+    aCallState = ECallStateIdle;
+    TRACE("CVtMediatorPlugin.ClearData>" )
+    }
+
+// -----------------------------------------------------------------------------
+// CVtMediatorPlugin::RegisterVtInternalEventL
+//
+// 
+// -----------------------------------------------------------------------------
+//
+void CVtMediatorPlugin::RegisterVtInternalEventL()
+    {
+    TRACE("CVtMediatorPlugin.RegisterVtInternalEventL<" )
+    iEventProvider = CMediatorEventProvider::NewL();
+    
+    TVersion version(
+        KVideotelMdtrEventVersionMajor,
+        KVideotelMdtrEventVersionMinor,
+        KVideotelMdtrEventVersionBuild );
+
+    TCapabilitySet capSet;
+    capSet.SetEmpty();
+    capSet.AddCapability( ECapabilityReadDeviceData );
+            
+    const TInt err = iEventProvider->RegisterEvent(
+        KMediatorVideoTelephonyDomain,
+        KCatVideotelInternalEvents,
+        EVtMediatorEventVideoCallInformation,
+        version,
+        capSet );
+          
+   
+    TRACE2("CVtMediatorPlugin.RegisterVtInternalEventL err=%d>", err )
+    User::LeaveIfError( err );
+    }
+
+// -----------------------------------------------------------------------------
+// CVtMediatorPlugin::RegisterDataportCommandL
+//
+// 
+// -----------------------------------------------------------------------------
+//
+void CVtMediatorPlugin::RegisterDataportCommandL()
+    {
+    TRACE("CVtMediatorPlugin.RegisterDataportCommandL<" )
+    iCommandResponder = CMediatorCommandResponder::NewL( this );
+    
+    TCapabilitySet capSet;
+    capSet.SetEmpty();
+    capSet.AddCapability( ECapabilityWriteDeviceData );
+    MediatorService::TCommand command;
+    
+    command.iCaps = capSet;
+    command.iVersion = TVersion( 
+            KPhoneToVideotelCmdVersionMajor, 
+            KPhoneToVideotelCmdVersionMinor,
+            KPhoneToVideotelCmdVersionBuild );
+    command.iTimeout = KVtEngMdtrCmdTimeout;
+        
+    // enable microphone command
+    command.iCommandId = EVtCmdUseDataport;
+    iCommandList.Append( command );
+        
+    // Releasedataport command
+    capSet.SetEmpty();
+    capSet.AddCapability( ECapabilityPowerMgmt );
+    command.iCommandId = EVtCmdReleaseDataport;
+    iCommandList.Append( command );
+    
+    const TInt err = iCommandResponder->RegisterCommand( 
+        KMediatorVideoTelephonyDomain,
+        KCatPhoneToVideotelCommands,
+        iCommandList );    
+    
+    TRACE2("CVtMediatorPlugin.RegisterDataportCommandL err=%d>", err )
+    User::LeaveIfError( err );
+    }
+
+// -----------------------------------------------------------------------------
+// CVtMediatorPlugin::RaiseVtEventL
+//
+// Raises VT call info event if in suitable state, i.e. VT app has subscribed 
+// the event.
+// -----------------------------------------------------------------------------
+//
+void CVtMediatorPlugin::RaiseVtEventL()
+    {
+    TRACE("CVtMediatorPlugin.RaiseVtEventL<" )
+    TInt result = KVtAppNotReady;  // does not cause leave
+    TRACE2("CVtMediatorPlugin.RaiseVtEventL iState=%d>", 
+            iState )
+    TRACE2("CVtMediatorPlugin.RaiseVtEventL iActiveVideoCallState=%d>", 
+            iActiveVideoCallState )            
+    if ( iState == EReady && // application subscribed to the event
+    
+        // don't send event if video call is not starting/ongoing
+         ( iActiveVideoCallState >= ECallStateDialling &&
+         iActiveVideoCallState <= ECallStateConnected ) )
+        {
+        const TVersion version(
+            KVideotelMdtrEventVersionMajor,
+            KVideotelMdtrEventVersionMinor,
+            KVideotelMdtrEventVersionBuild );            
+            
+        const TVtMediatorInfoPackage pckg( iActiveVideoCallInfo );
+        result = iEventProvider->RaiseEvent(
+            KMediatorVideoTelephonyDomain,
+            KCatVideotelInternalEvents,
+            EVtMediatorEventVideoCallInformation,
+            version,
+            pckg
+            );
+        }
+    TRACE2("CVtMediatorPlugin.RaiseVtEventL result=%d>", result )
+    User::LeaveIfError( result );
+    }
+
+// -----------------------------------------------------------------------------
+// CVtMediatorPlugin::HandleCallStateChangeL
+//
+// Compares previous and new video call states and resolves based on result
+// if Video telephone applicaton should be launched.
+// -----------------------------------------------------------------------------
+//
+void CVtMediatorPlugin::HandleCallStateChangeL(
+    const TTelephonyCallDataParam& aData )
+    {
+    TRACE("CVtMediatorPlugin.HandleCallStateChangeL<" )    
+    
+    TRACE2("CVtMediatorPlugin.HandleCallStateChangeL calltype=%d>", 
+            aData.iCallType )
+    TRACE2("CVtMediatorPlugin.HandleCallStateChangeL saved Activecallid=%d>", 
+            iActiveVideoCallInfo.iCallId )
+    TRACE2("CVtMediatorPlugin.HandleCallStateChangeL saved Waitingcallid=%d>", 
+            iWaitingVideoCallInfo.iCallId )
+    TRACE2("CVtMediatorPlugin.HandleCallStateChangeL callid=%d>", 
+            aData.iCallId )   
+    TRACE2("CVtMediatorPlugin.HandleCallStateChangeL ActiveCallOldState=%d>", 
+            iActiveVideoCallState )
+    TRACE2("CVtMediatorPlugin.HandleCallStateChangeL WaitingCallOldState=%d>", 
+            iWaitingVideoCallState )
+    TRACE2("CVtMediatorPlugin.HandleCallStateChangeL NewState=%d>",
+            aData.iCallState )
+            
+    //if the call is waitingcall, just save/clear
+    if ( aData.iCallType == ECallTypeVideo ||       
+        // check also call id because in call clearing states call type may
+        // be unspecified but call id is saved in call setup and we can
+        // compare to it.
+         iActiveVideoCallInfo.iCallId == aData.iCallId  ||
+         iWaitingVideoCallInfo.iCallId == aData.iCallId )
+        {
+        TBool isWaitingCall = ETrue;
+        
+        /**
+         * firstly we should check the callid to identify if it is a waitingcal/activecall
+         * imagine the usecase that long press endkey to shutdown both calls.
+         * after that checking iState
+         */
+        if ( iWaitingVideoCallInfo.iCallId == aData.iCallId )
+            {
+            isWaitingCall =  ETrue;
+            }
+        else if ( iActiveVideoCallInfo.iCallId == aData.iCallId )
+            {
+            isWaitingCall = EFalse;
+            }
+        //no vt app launched, this happens while vt first launching or end key to shutdown both calls
+        else if ( iState == EWaitingAppLaunch )
+            {
+            isWaitingCall =  EFalse;
+            }
+        
+        TRACE2("CVtMediatorPlugin.HandleCallStateChangeL isWaitingCall=%d>",
+                isWaitingCall)
+        
+        TCallState& callState = isWaitingCall?iWaitingVideoCallState:iActiveVideoCallState;
+        TVtVideoTelephonyCallInformation& vtCallInfo = isWaitingCall?iWaitingVideoCallInfo:iActiveVideoCallInfo;
+            
+        TBool launchNeeded = KVtCallStateActionArray[ aData.iCallState ] -
+                    KVtCallStateActionArray[callState] > 0;
+        if ( isWaitingCall )
+            {
+            launchNeeded = EFalse;
+            }
+        callState = aData.iCallState;
+            
+        switch ( callState )
+            {
+            case ECallStateDialling:
+            case ECallStateRinging:
+            case ECallStateConnecting:
+            case ECallStateConnected:
+                SaveCallData( aData,  vtCallInfo);
+                break;
+            default:
+                // data becomes invalid in other states (=call clearing/idle)
+                ClearData(vtCallInfo, callState);
+                break;
+            }
+        if ( launchNeeded )
+            {
+            LaunchVtAppL();
+            }
+        if ( !isWaitingCall )
+            {
+            RaiseVtEventL();
+            }
+        }
+        
+    TRACE("CVtMediatorPlugin.HandleCallStateChangeL>" )
+    }
+
+// -----------------------------------------------------------------------------
+// CVtMediatorPlugin::IsEnoughMemory
+//
+// Check if there is enough memory to launch
+// -----------------------------------------------------------------------------
+//
+TBool CVtMediatorPlugin::IsEnoughMemory()
+    {
+    TRACE("CVtMediatorPlugin::IsEnoughMemory<" )    
+    // Fetch amount of free memory.
+    TMemoryInfoV1Buf memory;
+    UserHal::MemoryInfo( memory );
+    TInt freeRam = (TInt)( memory().iFreeRamInBytes );
+    TRACE2("CVtMediatorPlugin::IsEnoughMemory: freeRam = %d", freeRam )
+    
+    TBool enoughRam = ETrue;
+
+    if ( freeRam < KRamNeededForVideoCalls )
+        {
+        FreeRam();
+        freeRam = (TInt)( memory().iFreeRamInBytes );
+        TRACE2("CVtMediatorPlugin::IsEnoughMemory: after free, freeRam = %d", freeRam )
+        if ( freeRam < KRamNeededForVideoCalls )
+            {
+            enoughRam = EFalse;
+            TRACE ("CVtMediatorPlugin::IsEnoughMemory : Not enough RAM")
+                
+            }
+        }
+    TRACE("CVtMediatorPlugin::IsEnoughMemory>" )    
+    return enoughRam;
+    }  
+// -----------------------------------------------------------------------------
+// CVtMediatorPlugin::FreeRam
+// Try to free memory to match the memory usage of VT
+// -----------------------------------------------------------------------------
+//
+void CVtMediatorPlugin::FreeRam()
+    {
+    TRACE("CVtMediatorPlugin.FreeRam()<")
+    User::CompressAllHeaps();
+    TRACE("CVtMediatorPlugin.FreeRam()>")
+    }
+
+// -----------------------------------------------------------------------------
+// CVtMediatorPlugin::StopDeathActiveL
+// -----------------------------------------------------------------------------
+//
+void CVtMediatorPlugin::StopDeathActiveL()
+    {
+    TRACE("CVtMediatorPlugin.StopDeathActive<")
+    delete iAppDeathActive;
+    iAppThread.Close();
+    iWsSession.Close();
+    //if there is a waiting call, check if we need to launch it
+    TRACE2("CVtMediatorPlugin.StopDeathActive WaitintCallID=%d>",
+            iWaitingVideoCallInfo.iCallId)
+    if ( iWaitingVideoCallInfo.iCallId != KVtInitCallId )
+        {
+        iActiveVideoCallInfo = iWaitingVideoCallInfo;
+        iActiveVideoCallState = iWaitingVideoCallState;
+        ClearData(iWaitingVideoCallInfo, iWaitingVideoCallState);
+        
+        if ( iActiveVideoCallState == ECallStateDialling ||
+                iActiveVideoCallState ==  ECallStateRinging ||
+                iActiveVideoCallState == ECallStateConnecting ||
+                iActiveVideoCallState == ECallStateConnected ||
+                iActiveVideoCallState == ECallStateAnswering )
+                {
+                LaunchVtAppL();
+                RaiseVtEventL();
+                }
+        }
+    TRACE("CVtMediatorPlugin.StopDeathActive>")
+    }
+// -----------------------------------------------------------------------------
+// CVtMediatorPlugin::CAppDeathActive::CAppDeathActive
+// -----------------------------------------------------------------------------
+//
+CVtMediatorPlugin::CAppDeathActive::CAppDeathActive( 
+        CVtMediatorPlugin& aMediatorPlugin,
+        RThread& aAppThread
+    )
+    : CActive( CActive::EPriorityStandard ),
+      iMediatorPlugin( aMediatorPlugin ),
+      iAppThread( aAppThread )
+      
+    {
+    CActiveScheduler::Add( this );
+    }
+
+// -----------------------------------------------------------------------------
+// CVtMediatorPlugin::CAppDeathActive::~CAppDeathActive
+// -----------------------------------------------------------------------------
+//
+CVtMediatorPlugin::CAppDeathActive::~CAppDeathActive()
+    {
+    TRACE("CVtMediatorPlugin.~CAppDeathActive")
+    Cancel();
+    }
+
+// -----------------------------------------------------------------------------
+// CVtMediatorPlugin::CAppDeathActive::Start
+// -----------------------------------------------------------------------------
+//
+void CVtMediatorPlugin::CAppDeathActive::Start()
+    {
+    TRACE("CVtMediatorPlugin.Start<")
+    Cancel();
+    iAppThread.Logon( iStatus );
+    SetActive();
+    TRACE("CVtMediatorPlugin.Start>")
+    }
+
+// -----------------------------------------------------------------------------
+// CVtMediatorPlugin::CAppDeathActive::RunL
+// -----------------------------------------------------------------------------
+//
+void CVtMediatorPlugin::CAppDeathActive::RunL()
+    {
+    //do something here
+    TRACE("CVtMediatorPlugin.RunL<")
+    iMediatorPlugin.StopDeathActiveL();
+    TRACE("CVtMediatorPlugin.RunL>")
+      
+    }
+        
+// -----------------------------------------------------------------------------
+// CVtMediatorPlugin::CAppDeathActive::DoCancel
+// -----------------------------------------------------------------------------
+//
+void CVtMediatorPlugin::CAppDeathActive::DoCancel()
+    {
+    iAppThread.LogonCancel( iStatus );
+    }
+        
+// -----------------------------------------------------------------------------
+// CVtMediatorPlugin::CAppDeathActive::RunError
+// -----------------------------------------------------------------------------
+//
+TInt CVtMediatorPlugin::CAppDeathActive::RunError( TInt /*aError*/ )
+    {
+    return KErrNone;
+    }