mediator/src/Client/MediatorNotificationsBody.cpp
author Shabe Razvi <shaber@symbian.org>
Thu, 02 Sep 2010 16:01:42 +0100
branchRCL_3
changeset 62 c50786bbedec
parent 0 4e1aa6a622a0
permissions -rw-r--r--
Merge RCL_3 fixes with reverted delivery

/*
* Copyright (c) 2005 Nokia Corporation and/or its subsidiary(-ies). 
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of "Eclipse Public License v1.0"
* which accompanies this distribution, and is available
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
*
* Initial Contributors:
* Nokia Corporation - initial contribution.
*
* Contributors:
*
* Description:  An implementation for receiving command/event notifications and info.
*
*/


// INCLUDE FILES
#include    <e32base.h>
#include    "MediatorNotificationsBody.h"
#include    "MediatorServerClient.h"
#include    "Debug.h"


// CONSTANTS
const TInt KMediatorDefaultCommandCount = 10;
const TInt KMediatorDefaultEventCount = 10;

// ============================ MEMBER FUNCTIONS ===============================

CMediatorNotificationsBody::CMediatorNotificationsBody()
    : CActive( EPriorityNormal ), 
      iCommandArrayPtr(NULL, 0), 
      iEventArrayPtr(NULL, 0),
      iCategoryBuffer( iCategory ),
      iNotificationTypeBuffer( iNotificationType ),
      iDestroyed(NULL)
     
    {
    }

void CMediatorNotificationsBody::ConstructL()
    {
    LOG(_L("[Mediator Server]\t CMediatorNotificationsBody::ConstructL\n"));
    CActiveScheduler::Add( this );
    User::LeaveIfError( iMediatorServer.Connect() );
    }

CMediatorNotificationsBody* CMediatorNotificationsBody::NewL()
    {
    CMediatorNotificationsBody* self = new( ELeave ) CMediatorNotificationsBody;
    
    CleanupStack::PushL( self );
    self->ConstructL();
    CleanupStack::Pop( self );

    return self;
    }
    
CMediatorNotificationsBody::~CMediatorNotificationsBody()
    {
    Cancel();
    iMediatorServer.Close();
    iEventList.Close();
    iCommandList.Close();
    
    if ( iDestroyed ) // RunL is being executed
        {
        *iDestroyed = ETrue;
        }
    }

// -----------------------------------------------------------------------------
// CMediatorNotificationsBody::RunL
//  
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
void CMediatorNotificationsBody::RunL()
    {
    TRACE(Print(_L("[Mediator Server]\t CMediatorNotificationsBody::RunL status %d\n"), iStatus.Int() ));
    
    if ( iStatus < 0 )  // We have an error
        {
        ERROR_TRACE(Print(_L("[Mediator] CMediatorNotificationsBody::RunL: iStatus=%d\n"), iStatus.Int() ) );
        
        // Cleanup and return
        iCommandList.Reset();
        iEventList.Reset();
        return;
        }
    
    // Set the flag to the member variable that is updated by the destructor 
    // in case this instance is destroyed by observer callback.
    // Otherwise an attempt to manipulate member data after destruction will cause a panic.
    TBool destroyed = EFalse;
    // iDestroyed is set individually in each case in order to prevent erros if a leave occurs
    
    TInt err = KErrNone;
    
    // Act according to notification type. NOTE! All the observer callback-calls are trapped because
    // leave would cause a possible access violation in destructor (iDestoryed pointing to an non-existing variable)
    switch( iNotificationType )
        {
        case EMediatorEventsRegistered:
            {
            LOG(_L("[Mediator Server]\t Events registered\n"));
            if ( iObserver )
                {
                TBool fetchEvents = iStatus.Int() > iEventList.Count() ? ETrue : EFalse;
                
                ResizeEventListL( iStatus.Int() );
                
                if ( fetchEvents )
                    {
                    FetchEventListL();
                    }
                
                iDestroyed = &destroyed;
                TRAP( err, iObserver->MediatorEventsAddedL( iCategory.iDomain,
                                                            iCategory.iCategory,
                                                            iEventList ) );
                }
            break;
            }
        case EMediatorCommandsRegistered:
            {
            LOG(_L("[Mediator Server]\t Commands registered\n"));
            if ( iObserver )
                {
                TBool fetchCommands = iStatus.Int() > iCommandList.Count() ? ETrue : EFalse;
                
                ResizeCommandListL( iStatus.Int() );
                
                if ( fetchCommands )
                    {
                    FetchCommandListL();
                    }
                
                iDestroyed = &destroyed;    
                TRAP( err, iObserver->MediatorCommandsAddedL( iCategory.iDomain,
                                                              iCategory.iCategory,
                                                              iCommandList ) );
                }
            break;
            }
        case EMediatorEventsUnregistered:
            {
            LOG(_L("[Mediator Server]\t Events unregistered\n"));
            if ( iObserver )
                {
                TBool fetchEvents = iStatus.Int() > iEventList.Count() ? ETrue : EFalse;
                
                ResizeEventListL( iStatus.Int() );
                
                if ( fetchEvents )
                    {
                    FetchEventListL();
                    }
                
                iDestroyed = &destroyed;    
                TRAP( err, iObserver->MediatorEventsRemovedL( iCategory.iDomain,
                                                              iCategory.iCategory,
                                                              iEventList ) );
                }
            break;
            }
        case EMediatorCommandsUnregistered:
            {
            LOG(_L("[Mediator Server]\t Commands unregistered\n"));
            if ( iObserver )
                {
                TBool fetchCommands = iStatus.Int() > iCommandList.Count() ? ETrue : EFalse;
                
                ResizeCommandListL( iStatus.Int() );
                
                if ( fetchCommands )
                    {
                    FetchCommandListL();
                    }
                
                iDestroyed = &destroyed;    
                TRAP( err, iObserver->MediatorCommandsRemovedL( iCategory.iDomain,
                                                                iCategory.iCategory,
                                                                iCommandList ) );
                }
            break;
            }
        case EMediatorCategoryUnregistered:
            {
            
            LOG(_L("[Mediator Server]\t Category unregistered\n"));
            if ( iObserver )
                {
                iDestroyed = &destroyed;
                TRAP( err, iObserver->MediatorCategoryRemovedL( iCategory.iDomain,
                                                                iCategory.iCategory ) );
                }
            break;
            }
        default:
            {
            LOG(_L("[Mediator Server]\t Unknown notification\n"));
            break;
            }
        }
    
    
    if ( err != KErrNone )
        {
        ERROR_TRACE(Print(_L("[Mediator] CMediatorNotificationsBody::RunL: err=%d, iNotificationType=%d\n"), err,
                                                                                                             iNotificationType ) );
        if ( !destroyed )
            {
            iDestroyed = NULL;
            }
            
        User::Leave( err ); // leave now, if an observer callback caused an error
        }
    
    if ( !destroyed ) // client may delete instance in observer callback
        {
        iDestroyed = NULL; // set to NULL, because local variable goes out of scope soon
        // Continue receiving notifications
        ReceiveNotificationsL();    
        }
    
    }
        
// -----------------------------------------------------------------------------
// CMediatorNotificationsBody::DoCancel
//  
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
void CMediatorNotificationsBody::DoCancel()
    {
    LOG(_L("[Mediator Server]\t CMediatorNotificationsBody::DoCancel\n"));  
    iMediatorServer.Cancel(); 
    }

// -----------------------------------------------------------------------------
// CMediatorNotificationsBody::RegisterNotificationObserver
//  
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
TInt CMediatorNotificationsBody::RegisterNotificationObserver( 
            MMediatorNotifications* aObserver )
    {
    iObserver = aObserver;
    //return ReceiveNotifications();
    
    TRAPD ( err, ReceiveNotificationsL() );
    
    return err;
    }
            
// -----------------------------------------------------------------------------
// CMediatorNotificationsBody::UnregisterNotificationObserver
//  
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
TInt CMediatorNotificationsBody::UnregisterNotificationObserver()
    {
    iObserver = NULL;
    // Empty existing arrays
    if ( iCommandList.Count() > 0 )
        {
        iCommandList.Reset();
        }
    if ( iEventList.Count() > 0 )
        {
        iEventList.Reset();
        }
    // Cancel the show
    return iMediatorServer.CancelNotifications();
    }

// -----------------------------------------------------------------------------
// CMediatorNotificationsBody::GetDomains
// Gets a list of registered domains
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
TInt CMediatorNotificationsBody::GetDomains( RDomainList& aDomains )
    {
    LOG(_L("[Mediator Server]\t CMediatorNotificationsBody::GetDomains\n"));
    return iMediatorServer.GetDomains( aDomains );
    }
    

// -----------------------------------------------------------------------------
// CMediatorNotificationsBody::GetCategories
// Gets a list of registered domains
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
TInt CMediatorNotificationsBody::GetCategories( TUid aDomain, 
                                                RCategoryList& aCategories )
    {
    LOG(_L("[Mediator Server]\t CMediatorNotificationsBody::GetCategories\n"));
    return iMediatorServer.GetCategories( aDomain, aCategories );
    }

// -----------------------------------------------------------------------------
// CMediatorNotificationsBody::GetEvents
// Gets a list of registered events withing the domain/category
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
TInt CMediatorNotificationsBody::GetEvents( TUid aDomain, 
                                            TUid aCategory,
                                            REventList& aEvents )
    {
    LOG(_L("[Mediator Server]\t CMediatorNotificationsBody::GetEvents\n"));
    return iMediatorServer.GetEvents( aDomain, aCategory, aEvents );
    }

// -----------------------------------------------------------------------------
// CMediatorNotificationsBody::GetCommands
// Gets a list of registered commands withing the domain/category
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
TInt CMediatorNotificationsBody::GetCommands( TUid aDomain, 
                                              TUid aCategory,
                                              RCommandList& aCommands )
    {
    LOG(_L("[Mediator Server]\t CMediatorNotificationsBody::GetCommands\n"));
    return iMediatorServer.GetCommands( aDomain, aCategory, aCommands );
    }


// -----------------------------------------------------------------------------
// CMediatorNotificationsBody::ReceiveNotificationsL
// 
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//

void CMediatorNotificationsBody::ReceiveNotificationsL()
    {
    LOG(_L("[Mediator Server]\t CMediatorNotificationsBody::ReceiveNotificationsL\n"));
    if ( IsActive() )
        {
        ERROR_LOG(_L("[Mediator] CMediatorNotificationsBody::ReceiveNotificationsL: User::Leave( KErrAlreadyExists )\n") );
        User::Leave( KErrAlreadyExists );
        }
        
    ResizeEventListL( KMediatorDefaultEventCount );
    
    ResizeCommandListL ( KMediatorDefaultCommandCount );
    
    // Define data return pointers
    TInt commandArraySize = ( sizeof(MediatorService::TCommand) ) * KMediatorDefaultCommandCount; 
    TPtr8 commandArrayPtr( (TUint8*)&iCommandList[0], commandArraySize );
    iCommandArrayPtr.Set( commandArrayPtr );
    
    TInt eventArraySize = ( sizeof(MediatorService::TEvent) ) * KMediatorDefaultEventCount; 
    TPtr8 eventArrayPtr( (TUint8*)&iEventList[0], eventArraySize );
    iEventArrayPtr.Set( eventArrayPtr );
    
    SetActive();
    
    iMediatorServer.ReceiveNotifications( iStatus,
                                          iCategoryBuffer, 
                                          iNotificationTypeBuffer,
                                          iEventArrayPtr,
                                          iCommandArrayPtr );
    }

// -----------------------------------------------------------------------------
// CMediatorNotificationsBody::ResizeEventListL
// 
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
void CMediatorNotificationsBody::ResizeEventListL( TInt aEventCount )
    {
    LOG(_L("[Mediator Server]\t CMediatorNotificationsBody::ResizeEventListL\n"));
    if ( iEventList.Count() > aEventCount ) // less events has been received than space allocated
        {
        // suppress list
        for ( TInt i = iEventList.Count() - 1; i >= aEventCount; i-- )
            {
            iEventList.Remove( i );
            }
        }
    else if ( iEventList.Count() < aEventCount )  // more events than initially/previously allocated
        {
        // reallocate event list
        iEventList.Reset();
        
        User::LeaveIfError( iEventList.Reserve( aEventCount ) );
        
        for ( TInt i = 0; i < aEventCount; i++ )
            {
            TEvent emptyEvent;
            iEventList.Append( emptyEvent );
            }    
        }
    }

// -----------------------------------------------------------------------------
// CMediatorNotificationsBody::ResizeCommandListL
// 
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
void CMediatorNotificationsBody::ResizeCommandListL( TInt aCommandCount )
    {
    LOG(_L("[Mediator Server]\t CMediatorNotificationsBody::ResizeCommandListL\n"));
    if ( iCommandList.Count() > aCommandCount ) // less commands has been received than space allocated
        {
        // suppress list
        for ( TInt i = iCommandList.Count() - 1; i >= aCommandCount; i-- )
            {
            iCommandList.Remove( i );
            }
        }
    else if ( iCommandList.Count() < aCommandCount )  // more commands than initially/previously allocated
        {
        // reallocate command list
        iCommandList.Reset();
        
        User::LeaveIfError( iCommandList.Reserve( aCommandCount) );
        
        for ( TInt i = 0; i < aCommandCount; i++ )
            {
            TCommand emptyCommand;
            iCommandList.Append( emptyCommand );
            }    
        }
    }

// -----------------------------------------------------------------------------
// CMediatorNotificationsBody::FetchEventListL
// 
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
void CMediatorNotificationsBody::FetchEventListL()
    {
    LOG(_L("[Mediator Server]\t CMediatorNotificationsBody::FetchEventListL\n"));
    TInt eventArraySize = ( sizeof(MediatorService::TEvent) ) * iEventList.Count(); 
    TPtr8 eventArrayPtr( (TUint8*)&iEventList[0], eventArraySize );
    iEventArrayPtr.Set( eventArrayPtr );
    User::LeaveIfError( iMediatorServer.FetchNotificationEventList( iEventArrayPtr ) );
    }
    
// -----------------------------------------------------------------------------
// CMediatorNotificationsBody::FetchCommandListL
// 
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
void CMediatorNotificationsBody::FetchCommandListL()
    {
    LOG(_L("[Mediator Server]\t CMediatorNotificationsBody::FetchCommandListL\n"));
    TInt commandArraySize = ( sizeof(MediatorService::TCommand) ) * iCommandList.Count(); 
    TPtr8 commandArrayPtr( (TUint8*)&iCommandList[0], commandArraySize );
    iCommandArrayPtr.Set( commandArrayPtr );
    User::LeaveIfError( iMediatorServer.FetchNotificationCommandList( commandArrayPtr ) );
    }

// ----------------------------------------------------------------------------
// CStartupMediatorPluginSubscriber::RunError()
// ----------------------------------------------------------------------------
#ifdef _DEBUG
TInt CMediatorNotificationsBody::RunError( TInt aError )
#else
TInt CMediatorNotificationsBody::RunError( TInt /*aError*/ )
#endif //_DEBUG
    {
    ERROR_TRACE(Print(_L("[Mediator] CMediatorNotificationsBody::RunError: err=%d\n"), aError));

    // Return KErrNone to avoid panic
    return KErrNone;
    }

//  End of File