hwrmhaptics/hapticspluginmanager/src/hwrmhapticscommondata.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Wed, 18 Aug 2010 11:03:14 +0300
changeset 54 072a9626b290
parent 0 4e1aa6a622a0
permissions -rw-r--r--
Revision: 201033 Kit: 201033

/*
* 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:  Haptics common data class definition
*
*/


#include "hwrmhapticstrace.h"
#include "hwrmhapticscommondata.h"


// ---------------------------------------------------------------------------
// Two-phased constructor.
// ---------------------------------------------------------------------------
//
EXPORT_C CHWRMHapticsCommonData* CHWRMHapticsCommonData::NewL()
    {
    COMPONENT_TRACE( ( _L( "CHWRMHapticsCommonData::NewL()" ) ) );

    CHWRMHapticsCommonData* self = new( ELeave ) CHWRMHapticsCommonData();
    CleanupStack::PushL( self );

    self->ConstructL();

    CleanupStack::Pop( self );

    COMPONENT_TRACE( ( _L( "CHWRMHapticsCommonData::NewL - return 0x%x" ), self ) );
    
    return self;
    }
   
// ---------------------------------------------------------------------------
// Destructor
// ---------------------------------------------------------------------------
//
CHWRMHapticsCommonData::~CHWRMHapticsCommonData()
    {
    COMPONENT_TRACE( ( _L( "CHWRMHapticsCommonData::~CHWRMHapticsCommonData()" ) ) );

    iClientArray.ResetAndDestroy();
    iClientArray.Close();

    iActuatorEvents.Close();
    
    COMPONENT_TRACE( ( _L( "CHWRMHapticsCommonData::~CHWRMHapticsCommonData - return" ) ) );
    }

// ---------------------------------------------------------------------------
// Adds a new session to client array.
// ---------------------------------------------------------------------------
//
void CHWRMHapticsCommonData::AddSessionL( const CSession2* aSession )
    {
    // create new client status data
    TClientStatus* clientStatus = 
        new (ELeave) TClientStatus( aSession, iGeneralStatus );
    CleanupStack::PushL( clientStatus );
    
    iClientArray.AppendL( clientStatus );
    
    CleanupStack::Pop( clientStatus );
    }

// ---------------------------------------------------------------------------
// Removes a session from the client array.
// ---------------------------------------------------------------------------
//
void CHWRMHapticsCommonData::RemoveSession( const CSession2* aSession )
    {
    // find the index of the client
    TInt index = FindClient( aSession );
    
    // remove status related data of the session/client
    if ( index != KErrNotFound )
        {
        // complete the observer, if it has been set
        if ( iClientArray[index]->iStatusObserver.Handle() )
            {
            // with completion code KErrCancel the client should stop 
            // requesting notifications
            iClientArray[index]->iStatusObserver.Complete( KErrCancel );
            }

        // delete and remove session/client from the array
        delete iClientArray[index];
        iClientArray.Remove( index );
        }
    }

// ---------------------------------------------------------------------------
// Adds the given message as a haptics status observer.
// ---------------------------------------------------------------------------
//
void CHWRMHapticsCommonData::AddStatusObserver( 
                                        const RMessage2& aStatusObserverMsg )
    {
    // find the index of the client
    TInt index = FindClient( aStatusObserverMsg.Session() );
    
    if ( index != KErrNotFound )
        {
        // set new observer message
        iClientArray[index]->iStatusObserver = aStatusObserverMsg;
        
        // read and set request types value
        THWRMHapticsStatusTypes reqTypes = 
            static_cast<THWRMHapticsStatusTypes>( aStatusObserverMsg.Int0() );

        iClientArray[index]->iStatusTypes = reqTypes;
        
        // send notification of the current status, if it is needed
        // for this client
        if ( iClientArray[index]->iNotificationRequired )
            {
            NotifyStatus( iClientArray[index]->iStatus, 
                          aStatusObserverMsg.Session() );

            iClientArray[index]->iNotificationRequired = EFalse;
            }
        else if ( iClientArray[index]->iRequiredActuators.Count() )
            {
            // there are unsent actuator event notifications, 
            // send immediately
            THWRMLogicalActuators actuator = 
                iClientArray[index]->iRequiredActuators[0];
            
            // search for the event
            TInt eventIndex = FindActuatorEvent( actuator );
            
            // send notification, if event found
            if ( eventIndex != KErrNotFound )
                {
                NotifyActuatorEventToClient( 
                                index, 
                                iActuatorEvents[eventIndex].iActuatorEvent, 
                                iActuatorEvents[eventIndex].iActuator );
                }
            
            // remove the actuator from required event notification array
            iClientArray[index]->iRequiredActuators.Remove( 0 );
            }
        }
    }

// ---------------------------------------------------------------------------
// Notifies the given haptics status to the observer identified
// with the given session, if the observer message exists.
// ---------------------------------------------------------------------------
//
void CHWRMHapticsCommonData::NotifyStatus( 
                            MHWRMHapticsObserver::THWRMHapticsStatus aStatus,
                            const CSession2* aSession )
    {
    // get the index of the observer to be notified
    TInt index = FindClient( aSession );
    
    // notify observer and store status
    NotifyStatusToClient( index, aStatus );
    }

// ---------------------------------------------------------------------------
// Notifies the last event of the given actuator to the observer
// identified with the given session.
// ---------------------------------------------------------------------------
//
void CHWRMHapticsCommonData::NotifyActuatorEvent( 
                                            THWRMLogicalActuators aActuator,
                                            const CSession2* aSession )
    {
    // get the index of the observer to be notified
    TInt clientIndex = FindClient( aSession );
    
    // try to find the event data
    TInt eventIndex = FindActuatorEvent( aActuator );

    // if client and event were found, notify client
    if ( clientIndex != KErrNotFound && eventIndex != KErrNotFound )
        {
        NotifyActuatorEventToClient( 
                        clientIndex, 
                        iActuatorEvents[eventIndex].iActuatorEvent, 
                        iActuatorEvents[eventIndex].iActuator );
        }
    }

// ---------------------------------------------------------------------------
// Notifies all observers except the one identified with the given
// session using the given haptics status.
// ---------------------------------------------------------------------------
//
void CHWRMHapticsCommonData::BroadcastStatus( 
                            MHWRMHapticsObserver::THWRMHapticsStatus aStatus,
                            const CSession2* aSession )
    {
    // notify all clients, except the one with given session
    for ( TInt i = 0; i < iClientArray.Count(); ++i )
        {
        if ( iClientArray[i]->iSession != aSession )
            {
            NotifyStatusToClient( i, aStatus );
            }
        }

    iGeneralStatus = aStatus;
    }

// ---------------------------------------------------------------------------
// Notifies all observers listening to actuator events using the 
// given event and actuator type values.
// ---------------------------------------------------------------------------
//
void CHWRMHapticsCommonData::BroadcastActuatorEvent( 
                MHWRMHapticsActuatorObserver::THWRMActuatorEvents aEvent,
                THWRMLogicalActuators aActuator )
    {
    // notify all clients listening to actuator events
    for ( TInt i = 0; i < iClientArray.Count(); ++i )
        {
        if ( iClientArray[i]->iStatusTypes == EHWRMHapticsActuatorStatus ||
             iClientArray[i]->iStatusTypes == EHWRMHapticsBothStatus )
            {
            NotifyActuatorEventToClient( i, aEvent, aActuator );
            }
        }
    
    // store actuator event, so that it can be sent, if notification did not
    // succeed above
    StoreActuatorEvent( aEvent, aActuator );
    }

// ---------------------------------------------------------------------------
// Returns the current status of the given session.
// ---------------------------------------------------------------------------
//
MHWRMHapticsObserver::THWRMHapticsStatus
CHWRMHapticsCommonData::CurrentStatus( const CSession2* aSession ) const
    {
    // get the index of the client
    TInt index = FindClient( aSession );

    return iClientArray[index]->iStatus;
    }

// ---------------------------------------------------------------------------
// Returns the index of the observer with given session.
// ---------------------------------------------------------------------------
//
TInt CHWRMHapticsCommonData::FindClient( const CSession2* aSession ) const
    {
    TInt ret = KErrNotFound;
    
    // find the observer with the given session
    for ( TInt i = 0; i < iClientArray.Count() && ret == KErrNotFound; ++i )
        {
        if ( iClientArray[i]->iSession == aSession )
            {
            ret = i;
            }
        }
    
    return ret;
    }

// ---------------------------------------------------------------------------
// Returns the index of the actuator event in the event array.
// ---------------------------------------------------------------------------
//
TInt CHWRMHapticsCommonData::FindActuatorEvent( 
                                    THWRMLogicalActuators aActuator ) const
    {
    TInt ret = KErrNotFound;
    
    // find the event with the given actuator
    for ( TInt i = 0; i < iActuatorEvents.Count() && ret == KErrNotFound; ++i )
        {
        if ( iActuatorEvents[i].iActuator == aActuator )
            {
            ret = i;
            }
        }
    
    return ret;
    }

// ---------------------------------------------------------------------------
// Updates given actuators status, or if not found, inserts new
// data for the actuator.
// ---------------------------------------------------------------------------
//
void CHWRMHapticsCommonData::StoreActuatorEvent( 
                                        TActuatorStatus aStatus, 
                                        THWRMLogicalActuators aActuator )
    {
    // try to find the event data
    TInt index = FindActuatorEvent( aActuator );

    if ( index != KErrNotFound )
        {
        // data was found, update it
        iActuatorEvents[index].iActuatorEvent = aStatus;
        iActuatorEvents[index].iActuator = aActuator;
        }
    else
        {
        // data was not found, create new data
        TActuatorEvent event( aStatus, aActuator );
        iActuatorEvents.Append( event );
        }
    }

// ---------------------------------------------------------------------------
// Implements the actual notification to the client and stores the status
// for the indexed client data.
// ---------------------------------------------------------------------------
//
void CHWRMHapticsCommonData::NotifyStatusToClient( 
                        TInt aIndex,
                        MHWRMHapticsObserver::THWRMHapticsStatus aStatus )
    {
    // notify only if the client has an observer and client has requested
    // haptics status notification
    if ( iClientArray[aIndex]->iStatusObserver.Handle() && 
         ( iClientArray[aIndex]->iStatusTypes == EHWRMHapticsSessionStatus ||
           iClientArray[aIndex]->iStatusTypes == EHWRMHapticsBothStatus ) )
        {
        // create status package
        TPckg<THWRMHapticsStatusTypes> statusTypePckg( EHWRMHapticsSessionStatus );
        TPckg<TInt> statusPckg( aStatus );
        
        // write type and status to message and complete it. Completing the 
        // message sets the handle in the message to zero, which is used to 
        // notice that the message has already been completed.
        TInt err = iClientArray[aIndex]->iStatusObserver.Write( 1, statusTypePckg, 0 );
        err = iClientArray[aIndex]->iStatusObserver.Write( 2, statusPckg, 0 );
        iClientArray[aIndex]->iStatusObserver.Complete( err );
        }
    else
        {
        // status was not sent to client, so it needs to be sent, when
        // the client requests status notification for the next time
        iClientArray[aIndex]->iNotificationRequired = ETrue;
        }
    
    // store the status value for the client even if it was not sent to
    // an observer so that it can be fetched by a direct get status -command
    iClientArray[aIndex]->iStatus = aStatus;
    }

// ---------------------------------------------------------------------------
// Implements the actual actuator event notification to the client.
// ---------------------------------------------------------------------------
//
void CHWRMHapticsCommonData::NotifyActuatorEventToClient( 
                                            TInt aIndex, 
                                            TActuatorStatus aStatus,
                                            THWRMLogicalActuators aActuator )
    {
    // notify or store data for client only if client has requested actuator
    // event notification
    if ( iClientArray[aIndex]->iStatusTypes == EHWRMHapticsActuatorStatus ||
         iClientArray[aIndex]->iStatusTypes == EHWRMHapticsBothStatus )
        {
        // notify only if the client has an observer
        if ( iClientArray[aIndex]->iStatusObserver.Handle() )
            {
            // create type, status and actuator packages
            TPckg<THWRMHapticsStatusTypes> statusTypePckg( EHWRMHapticsActuatorStatus );
            TPckg<TInt> statusPckg( aStatus );
            TPckg<THWRMLogicalActuators> actuatorPckg( aActuator );
            
            // write type, status and actuator to message and complete it. 
            // Completing the message sets the handle in the message to zero, 
            // which is used to notice that the message has already been 
            // completed.
            TInt err = iClientArray[aIndex]->iStatusObserver.Write( 1, statusTypePckg, 0 );
            err = iClientArray[aIndex]->iStatusObserver.Write( 2, statusPckg, 0 );
            err = iClientArray[aIndex]->iStatusObserver.Write( 3, actuatorPckg, 0 );
            iClientArray[aIndex]->iStatusObserver.Complete( err );
            }
        else
            {
            // event was not sent to client, so it needs to be sent, when
            // the client requests notification for the next time
            TInt index = iClientArray[aIndex]->iRequiredActuators.Find( aActuator );
            if ( index == KErrNotFound )
                {
                // actuator was not in the list already --> needs to be added
                iClientArray[aIndex]->iRequiredActuators.Append( aActuator );
                }
            }
        }
    }

// ---------------------------------------------------------------------------
// C++ constructor.
// ---------------------------------------------------------------------------
//
CHWRMHapticsCommonData::CHWRMHapticsCommonData()
    : iGeneralStatus( MHWRMHapticsObserver::EHWRMHapticsStatusAvailable )
    {
    COMPONENT_TRACE( ( _L( "CHWRMHapticsCommonData::CHWRMHapticsCommonData()" ) ) );
    COMPONENT_TRACE( ( _L( "CHWRMHapticsCommonData::CHWRMHapticsCommonData - return" ) ) );
    }

// ---------------------------------------------------------------------------
// Symbian 2nd phase constructor can leave.
// ---------------------------------------------------------------------------
//
void CHWRMHapticsCommonData::ConstructL()
    {    
    COMPONENT_TRACE( ( _L( "CHWRMHapticsCommonData::ConstructL()" ) ) );
    COMPONENT_TRACE( ( _L( "CHWRMHapticsCommonData::ConstructL - return" ) ) );
    }

//  End of File