mpx/commonframework/common/src/mpxclientlist.cpp
changeset 0 a2952bb97e68
child 9 bee149131e4b
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mpx/commonframework/common/src/mpxclientlist.cpp	Thu Dec 17 08:55:47 2009 +0200
@@ -0,0 +1,604 @@
+/*
+* Copyright (c) 2006 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:  Encapsulates all the clients
+*
+*/
+
+
+// INCLUDES
+#include <mpxlog.h>
+#include "mpxuser.h"
+#include "mpxmessagequeue.h"
+#include "mpxclientlistobserver.h"
+#include "mpxclientlist.h"
+#include <mpxsubscription.h>
+
+// ============================ MEMBER FUNCTIONS ==============================
+
+// ----------------------------------------------------------------------------
+// Two-phased constructor.
+// ----------------------------------------------------------------------------
+//
+EXPORT_C CMPXClientList* CMPXClientList::NewL(
+    MMPXClientlistObserver* aObserver /*=NULL*/)
+    {
+    CMPXClientList* list=new(ELeave)CMPXClientList(aObserver);
+    CleanupStack::PushL(list);
+    list->ConstructL();
+    CleanupStack::Pop(list);
+    return list;
+    }
+
+// ----------------------------------------------------------------------------
+// Constructor.
+// ----------------------------------------------------------------------------
+//
+CMPXClientList::CMPXClientList(MMPXClientlistObserver* aObserver)
+    : iIdentity(CMPXClientList::ClientsMatch),
+    iObserver(aObserver)
+    {}
+
+// ----------------------------------------------------------------------------
+// 2nd phase constructor.
+// ----------------------------------------------------------------------------
+//
+void CMPXClientList::ConstructL()
+    {
+    }
+
+// ----------------------------------------------------------------------------
+// Destructor
+// ----------------------------------------------------------------------------
+//
+EXPORT_C CMPXClientList::~CMPXClientList()
+    {
+    iClients.ResetAndDestroy();
+    iClients.Close();
+    iClientProcesses.Close();
+    }
+
+// ----------------------------------------------------------------------------
+// Add a client into the client list
+// ----------------------------------------------------------------------------
+//
+EXPORT_C void CMPXClientList::AddClientL(
+    TThreadId aId,
+    CMPXMessageQueue* aMsgQueue)
+    {
+    AddClientL(aId, KErrUnknown, aMsgQueue);
+    }
+
+// ----------------------------------------------------------------------------
+// Add a client into the client list
+// ----------------------------------------------------------------------------
+//
+EXPORT_C void CMPXClientList::AddClientL(
+    TThreadId aId,
+    TInt aMode,
+    CMPXMessageQueue* aMsgQueue)
+    {
+    TProcessId pid=MPXUser::ProcessIdL(aId);
+    CClientId* newClient = new(ELeave) CClientId(aId,pid,aMode,aMsgQueue);
+    CleanupStack::PushL(newClient);
+
+    // add an empty subscription by default
+    CMPXSubscription* subscription = CMPXSubscription::NewL();
+    CleanupStack::PushL(subscription);
+
+    // transfer the ownership
+    newClient->iSubscriptions.AppendL(subscription);
+    CleanupStack::Pop(subscription);
+
+    iClients.AppendL(newClient);
+    CleanupStack::Pop(newClient);
+
+    if (iClientProcesses.Find(pid)==KErrNotFound)
+        {
+        iClientProcesses.AppendL(pid);
+        if (iObserver)
+            {
+            iObserver->HandleClientChange(pid, MMPXClientlistObserver::EAdd);
+            }
+        }
+    }
+// ----------------------------------------------------------------------------
+// Add a client into the client list
+// ----------------------------------------------------------------------------
+//
+
+EXPORT_C void CMPXClientList::AddClientL(
+    TThreadId aId,
+    TInt aMode,
+    CMPXMessageQueue* aMsgQueue,
+    const TInt aCategory)
+    {
+    TProcessId pid=MPXUser::ProcessIdL(aId);
+    CClientId* newClient = new(ELeave) CClientId(aId,pid,aMode,aMsgQueue, aCategory);
+    CleanupStack::PushL(newClient);
+    // add an empty subscription by default
+    CMPXSubscription* subscription = CMPXSubscription::NewL();
+    CleanupStack::PushL(subscription);
+    // transfer the ownership
+    newClient->iSubscriptions.AppendL(subscription);
+    CleanupStack::Pop(subscription);
+    iClients.AppendL(newClient);
+    CleanupStack::Pop(newClient);
+    if (iClientProcesses.Find(pid)==KErrNotFound)
+        {
+        iClientProcesses.AppendL(pid);
+        if (iObserver)
+            {
+            iObserver->HandleClientChange(pid, MMPXClientlistObserver::EAdd);
+            }
+        }
+    }
+// SK
+// ----------------------------------------------------------------------------
+// Remove a client from the list
+// ----------------------------------------------------------------------------
+//
+EXPORT_C void CMPXClientList::RemoveClient(TInt aIndex)
+    {
+    // USER panic 130, if aIndex is negative or is greater than the number of
+    // objects currently in the array.
+    CClientId* id( iClients[aIndex] );
+    iClients.Remove(aIndex);
+
+    CClientId removeId( id->iPid );
+    if ( iClients.Find( &removeId, iIdentity ) == KErrNotFound )
+        //
+        // There's no other client from the same process, so
+        // remove it from the process list
+        //
+        {
+        TInt i=iClientProcesses.Find(id->iPid);
+        if (KErrNotFound != i)
+            {
+            if (iObserver)
+                {
+                iObserver->HandleClientChange(id->iPid, MMPXClientlistObserver::ERemove);
+                }
+            iClientProcesses.Remove(i);
+            }
+        }
+    delete id;
+    }
+
+// -----------------------------------------------------------------------------
+// Return the number of clients
+// -----------------------------------------------------------------------------
+//
+EXPORT_C TInt CMPXClientList::ClientCount() const
+    {
+    return iClients.Count();
+    }
+
+// -----------------------------------------------------------------------------
+// Return array of client process ids
+// -----------------------------------------------------------------------------
+//
+EXPORT_C TArray<TProcessId> CMPXClientList::ClientProcessList() const
+    {
+    return iClientProcesses.Array();
+    }
+
+// -----------------------------------------------------------------------------
+// Check if the client in the client list or not
+// -----------------------------------------------------------------------------
+//
+EXPORT_C TBool CMPXClientList::IsClient(TThreadId aId) const
+    {
+    return (KErrNotFound != Find(aId));
+    }
+
+// -----------------------------------------------------------------------------
+// Find a client denoted by message queue in this list.
+// -----------------------------------------------------------------------------
+//
+EXPORT_C TInt CMPXClientList::Find(const CMPXMessageQueue& aMsgQueue) const
+    {
+    CClientId id( const_cast<CMPXMessageQueue*>( &aMsgQueue ));
+    return iClients.Find( &id, iIdentity );
+    }
+
+// -----------------------------------------------------------------------------
+// Found a client by Id
+// -----------------------------------------------------------------------------
+//
+EXPORT_C TInt CMPXClientList::Find(TThreadId aId) const
+    {
+    CClientId id( aId );
+    return iClients.Find( &id ,iIdentity );
+    }
+
+// -----------------------------------------------------------------------------
+// Return client mode
+// -----------------------------------------------------------------------------
+//
+EXPORT_C TInt CMPXClientList::ClientMode(TInt aIndex) const
+    {
+    MPX_ASSERT(aIndex>=0 && aIndex<ClientCount());
+    return iClients[aIndex]->iMode;
+    }
+	
+
+// -----------------------------------------------------------------------------
+// Return client category
+// -----------------------------------------------------------------------------
+//
+EXPORT_C TInt CMPXClientList::ClientCategory(TInt aIndex) const
+    {
+    MPX_ASSERT(aIndex>=0 && aIndex<ClientCount());
+    TInt category = iClients[aIndex]->iCategory;
+    return category;
+    }
+
+	
+// -----------------------------------------------------------------------------
+// Send message to all clients in the list
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CMPXClientList::SendMsg(const CMPXMessage* aMsg, TInt aError)
+    {
+    MPX_FUNC_EX("CMPXClientList::SendMsg");
+    for (TInt i=iClients.Count();--i>=0;)
+        {
+        SendMsg( i, aMsg, aError );
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// Send message to a client
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CMPXClientList::SendMsg(
+    TInt aIndex,
+    const CMPXMessage* aMsg,
+    TInt aError)
+    {
+    MPX_FUNC_EX("CMPXClientList::SendMsgL(aIndex)");
+    MPX_ASSERT(aIndex>=0 && aIndex<iClients.Count());
+    MPX_ASSERT(iClients[aIndex]->iMsgQueue);
+
+    // check the subscriptions
+    TBool send(EFalse);
+    TInt err(KErrNone);
+    if (aMsg)
+        {
+        TRAP(err, send = IsMsgSubscribedL(aIndex, aMsg));
+        }
+    else
+        {
+        send = ETrue; // broadcast error message aError
+        }
+
+    // only send if the client has subscribed for it
+    if (send && KErrNone == err)
+        {
+        iClients[aIndex]->iMsgQueue->Add(aMsg, aError);
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CMPXClientList::AddSubscriptionL
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CMPXClientList::AddSubscriptionL(
+    TInt aIndex,
+    CMPXSubscription* aSubscription)
+    {
+    MPX_FUNC("CMPXClientList::AddSubscriptionL");
+
+    CClientId* id( iClients[aIndex] );
+    TInt subCount( id->iSubscriptions.Count() );
+    const CMPXMediaArray* items = id->iSubscriptions[0]->ItemsL();
+    // check if it has an empty subscription
+    if ( 1 == subCount  &&  items->Count() )
+        {
+        // remove it if so
+        id->RemoveAllSubscriptionsL();
+        }
+
+    // add the new subscription
+    id->AddSubscriptionL(aSubscription);
+    }
+
+// -----------------------------------------------------------------------------
+// CMPXClientList::RemoveSubscriptionL
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CMPXClientList::RemoveSubscriptionL(
+    TInt aIndex,
+    const CMPXSubscription& aSubscription)
+    {
+    MPX_FUNC("CMPXClientList::RemoveSubscriptionL");
+
+    iClients[aIndex]->RemoveSubscriptionL(aSubscription);
+    }
+
+// -----------------------------------------------------------------------------
+// CMPXClientList::RemoveAllSubscriptionsL
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CMPXClientList::RemoveAllSubscriptionsL(
+    TInt aIndex)
+    {
+    MPX_FUNC("CMPXClientList::RemoveAllSubscriptionsL");
+
+    iClients[aIndex]->RemoveAllSubscriptionsL();
+    }
+
+// -----------------------------------------------------------------------------
+// CMPXClientList::IsMsgSubscribedL
+// -----------------------------------------------------------------------------
+//
+TBool CMPXClientList::IsMsgSubscribedL(TInt aIndex, const CMPXMessage* aMsg)
+    {
+    // check the subscriptions
+    TBool IsSubScribed(EFalse);
+    TInt subCount(iClients[aIndex]->iSubscriptions.Count());
+
+    if (subCount)
+        {
+        const CMPXMediaArray* subscriptionItems =
+                                 iClients[aIndex]->iSubscriptions[0]->ItemsL();
+        if (1==subCount && (0== subscriptionItems->Count()))
+            {// one empty subscription - send everything
+            IsSubScribed = ETrue;
+            }
+        else
+            {// have to check the message against the subscriptions.
+            MPX_ASSERT(aMsg);
+            const TArray<TMPXAttribute> msgAttrs = aMsg->Attributes();
+            TInt msgAttrCount(msgAttrs.Count());
+            // iterate subscriptions
+            for (TInt subIndex = 0; subIndex<subCount && !IsSubScribed; ++subIndex)
+                {
+                // iterate items for the current subscription
+                subscriptionItems =
+                            iClients[aIndex]->iSubscriptions[subIndex]->ItemsL();
+                TInt itemCount(subscriptionItems->Count());
+                for (TInt itemIndex = 0; itemIndex < itemCount; ++itemIndex)
+                    {
+                    // check the message attributes for the current subscription item
+                    TBool subMatch(ETrue);
+                    TInt attrMatchCount(0);
+                    CMPXSubscriptionItem* subItem(subscriptionItems->AtL(itemIndex));
+
+                    for (TInt msgAttrIndex = 0; msgAttrIndex < msgAttrCount; ++msgAttrIndex)
+                        {
+                        TBool attrExists(EFalse);
+                        TBool attrMatch(EFalse);
+                        const TMPXAttribute& msgAttr( msgAttrs[msgAttrIndex] );
+
+                        if ( subItem->IsSupported(msgAttr))
+                            {
+                            attrExists = ETrue;
+
+                            if ( subItem->Match( *aMsg, msgAttr ))
+                                {
+                                attrMatch = ETrue;
+                                attrMatchCount++;
+                                }
+                            }
+
+                        if (attrExists && !attrMatch)
+                            {
+                            subMatch = EFalse;
+                            break;
+                            }
+                        }
+
+                    // send the message if all attributes that exist in both the message and the subscription
+                    // have the same values and all subscription attributes match
+                    if ( subMatch && ( attrMatchCount == subItem->Count()) )
+                        {
+                        IsSubScribed = ETrue;
+                        break;
+                        }
+                    }
+                }
+            }
+        } // else subCount = 0, IsSubScribed = EFalse (default)
+    return IsSubScribed;
+    }
+
+// ----------------------------------------------------------------------------
+// Comparison function. If the names are set in the client objects, then
+// that's used to test for equality. Otherwise, if the thread ids are set,
+// that's used. Else, it's assumed that the equality test is based on process
+//  ids.
+// ----------------------------------------------------------------------------
+//
+TBool CMPXClientList::ClientsMatch(const CClientId& aClient1,
+                                   const CClientId& aClient2)
+    {
+    TBool match=EFalse;
+    if (aClient1.iMsgQueue && aClient2.iMsgQueue)
+        {
+        match=aClient1.iMsgQueue==aClient2.iMsgQueue;
+        }
+    else if (aClient1.iTid.Id()!=KNullThreadId &&
+             aClient2.iTid.Id()!=KNullThreadId)
+        {
+        match=(aClient1.iTid==aClient2.iTid);
+        }
+    else
+        {
+        match=(aClient1.iPid==aClient2.iPid);
+        }
+    return match;
+    }
+
+// -----------------------------------------------------------------------------
+// C++ constructor
+// -----------------------------------------------------------------------------
+//
+CMPXClientList::CClientId::CClientId(
+    TThreadId aTid,
+    TProcessId aPid,
+    CMPXMessageQueue* aMsgQueue)
+:   iTid(aTid),
+    iPid(aPid),
+    iMode(KErrNotFound),
+    iMsgQueue(aMsgQueue)
+    {}
+
+// -----------------------------------------------------------------------------
+// C++ constructor
+// -----------------------------------------------------------------------------
+//
+CMPXClientList::CClientId::CClientId(
+    TThreadId aTid,
+    TProcessId aPid,
+    TInt aMode,
+    CMPXMessageQueue* aMsgQueue)
+:   iTid(aTid),
+    iPid(aPid),
+    iMode(aMode),
+    iMsgQueue(aMsgQueue)
+    {}
+
+
+// -----------------------------------------------------------------------------
+// C++ constructor
+// -----------------------------------------------------------------------------
+//
+    CMPXClientList::CClientId::CClientId(
+        TThreadId aTid,
+        TProcessId aPid,
+        TInt aMode,
+        CMPXMessageQueue* aMsgQueue,
+        TInt aCategory)
+    :   iTid(aTid),
+        iPid(aPid),
+        iMode(aMode),
+        iMsgQueue(aMsgQueue),
+        iCategory(aCategory)
+        {}
+
+// -----------------------------------------------------------------------------
+// C++ constructor
+// -----------------------------------------------------------------------------
+//
+CMPXClientList::CClientId::CClientId(CMPXMessageQueue* aMsgQueue)
+    :iTid(static_cast<TUint64>(KNullThreadId)),
+     iPid(static_cast<TUint64>(KNullProcessId)),
+     iMode(KErrUnknown),
+     iMsgQueue(aMsgQueue)
+    {}
+
+// -----------------------------------------------------------------------------
+// C++ constructor
+// -----------------------------------------------------------------------------
+//
+CMPXClientList::CClientId::CClientId(TThreadId aTid)
+:   iTid(aTid),
+    iPid(static_cast<TUint64>(KNullProcessId)),
+    iMode(KErrUnknown),
+    iMsgQueue(NULL)
+    {}
+
+// -----------------------------------------------------------------------------
+// C++ constructor
+// -----------------------------------------------------------------------------
+//
+CMPXClientList::CClientId::CClientId(TProcessId aPid)
+:   iTid(static_cast<TUint64>(KNullThreadId)),
+    iPid(aPid),
+    iMode(KErrUnknown),
+    iMsgQueue(NULL)
+    {}
+
+// -----------------------------------------------------------------------------
+// Destructor
+// -----------------------------------------------------------------------------
+//
+CMPXClientList::CClientId::~CClientId()
+    {
+    iSubscriptions.ResetAndDestroy();
+    }
+
+// -----------------------------------------------------------------------------
+// CClientId::operator=
+// -----------------------------------------------------------------------------
+//
+CMPXClientList::CClientId& CMPXClientList::CClientId::operator=(
+    const CClientId& aClient)
+    {
+    iTid = aClient.iTid;
+    iPid = aClient.iPid;
+    iMode = aClient.iMode;
+    iMsgQueue = aClient.iMsgQueue;
+
+    RemoveAllSubscriptionsL();
+
+    // copy the subscriptions
+    TInt count(aClient.iSubscriptions.Count());
+    for (TInt index = 0; index < count; ++index)
+        {
+        CMPXSubscription* subscription = static_cast<CMPXSubscription*>(
+            CMPXMedia::NewL(*(aClient.iSubscriptions[index])));
+        CleanupStack::PushL(subscription);
+
+        // transfer the ownership
+        iSubscriptions.AppendL(subscription);
+
+        CleanupStack::Pop(subscription);
+        }
+    return *this;
+    }
+
+// -----------------------------------------------------------------------------
+// CClientId::AddSubscriptionL
+// -----------------------------------------------------------------------------
+//
+void CMPXClientList::CClientId::AddSubscriptionL(
+    CMPXSubscription* aSubscription)
+    {
+    // add the subscription
+    iSubscriptions.AppendL(aSubscription);
+    }
+
+// -----------------------------------------------------------------------------
+// CClientId::RemoveSubscriptionL
+// -----------------------------------------------------------------------------
+//
+void CMPXClientList::CClientId::RemoveSubscriptionL(
+    const CMPXSubscription& aSubscription)
+    {
+    TInt count(iSubscriptions.Count());
+    for (TInt index = 0; index < count; ++index)
+        {
+        CMPXSubscription* subscription = iSubscriptions[index];
+        if (aSubscription == *subscription)
+            {
+            // found the subscription, remove it
+            iSubscriptions.Remove(index);
+            delete subscription;
+            break;
+            }
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CClientId::RemoveAllSubscriptionsL
+// -----------------------------------------------------------------------------
+//
+void CMPXClientList::CClientId::RemoveAllSubscriptionsL()
+    {
+    iSubscriptions.ResetAndDestroy();
+    }
+
+// End of File