--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/videofeeds/utils/inc/mtvobserverutils.inl Mon Jan 18 20:21:12 2010 +0200
@@ -0,0 +1,214 @@
+/*
+* Copyright (c) 2007 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of the License "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: Helper functions and macros for handling multiple observers.*
+*/
+
+
+
+
+#ifndef _MTV_OBSERVER_UTILS
+#define _MTV_OBSERVER_UTILS
+
+namespace MtvObserverUtils
+{
+
+/**
+ * Struct for holding a bunch of observers and a semaphore for controlling observer removal.
+ *
+ * @since Live TV UI v1.0
+ */
+template <class ObserverType, template<class> class ContainerType = RPointerArray, class PointerType = ObserverType>
+struct RObserverData
+ {
+ // constructor for initializing the semaphore
+ RObserverData() : iSemaphore(0), iShutdown(EFalse)
+ {
+ }
+ /**
+ * Initializes the container.
+ * This function is currently just a placeholder, later
+ * it can be used to add support for CBase-derived containers,
+ * assuming that all clients call OpenL and Close when using
+ * this class.
+ */
+ void OpenL()
+ {
+ }
+ /**
+ * Closes the container.
+ */
+ void Close()
+ {
+ iContainer.Close();
+ iShutdown = ETrue;
+ }
+ // Container can be RPointerArray, RArray..
+ // At the moment CBase-derived containers are not supported.
+ ContainerType<ObserverType> iContainer;
+ // the semaphore is used so that when it has a value greater than zero, observers
+ // are not removed, but nulled in the container
+ TInt iSemaphore;
+ // pointer type member helps code using this object, the using code does not
+ // need to know the actual observer type
+ PointerType* iObserver;
+ // Set to ETrue when the provider of notifications is shut down.
+ TBool iShutdown;
+ };
+
+/**
+ * Removes NULL observers from a container.
+ * @param aExistsNull Tells whether there are any NULL observers.
+ * Checking this parameter inside this function makes invoking code simpler.
+ * @param aObserverData Observer data object (usually a RObserverData).
+ * This data object must contain a container of observers and a semaphore.
+ */
+template <class ObserverDataType>
+static void RemoveNullObservers(TBool aExistsNull, ObserverDataType& aObserverData)
+ {
+ // semaphore must always be decremented
+ --aObserverData.iSemaphore;
+ if ( !aObserverData.iSemaphore && aExistsNull )
+ {
+ for (TInt i = aObserverData.iContainer.Count() - 1; i >= 0; --i)
+ {
+ if (aObserverData.iContainer[i] == NULL)
+ {
+ aObserverData.iContainer.Remove(i);
+ }
+ }
+ }
+ }
+
+/**
+ * Macro that invokes an observer function for all registered observers.
+ * @param aNotification Observer function to call.
+ * @param aObserverData Observer data object (usually a RObserverData).
+ * This data object must contain a container of observers and a semaphore.
+ */
+#define RUN_NOTIFY_LOOP(aNotification, aObserverData) \
+do \
+ { \
+ if ( !aObserverData.iShutdown )\
+ {\
+ ++aObserverData.iSemaphore; \
+ TBool existsNull = EFalse; \
+ const TInt count = aObserverData.iContainer.Count(); \
+ for ( TInt i = 0; i < count; ++i ) \
+ { \
+ aObserverData.iObserver = aObserverData.iContainer[ i ]; \
+ if ( aObserverData.iObserver ) \
+ { \
+ TRAP_IGNORE( aObserverData.iObserver->aNotification ); \
+ } \
+ else \
+ { \
+ existsNull = ETrue; \
+ } \
+ } \
+ RemoveNullObservers(existsNull, \
+ aObserverData); \
+ }\
+ } while (EFalse) \
+
+/**
+ * Macro that invokes an observer function for all registered observers.
+ * @param aNotification Observer function to call.
+ * @param aObserverData Observer data object (usually a RObserverData).
+ * @param aError On return, contains the possible first error code that happened.
+ * This data object must contain a container of observers and a semaphore.
+ */
+#define RUN_NOTIFY_LOOP_L(aNotification, aObserverData, aError) \
+do \
+ { \
+ aError = KErrNone; \
+ TInt ___mtvObserverUtilsNotifyLoopError = KErrNone; \
+ if ( !aObserverData.iShutdown )\
+ {\
+ ++aObserverData.iSemaphore; \
+ TBool existsNull = EFalse; \
+ const TInt count = aObserverData.iContainer.Count(); \
+ for ( TInt i = 0; i < count; ++i ) \
+ { \
+ aObserverData.iObserver = aObserverData.iContainer[ i ]; \
+ if ( aObserverData.iObserver ) \
+ { \
+ TRAP( ___mtvObserverUtilsNotifyLoopError, aObserverData.iObserver->aNotification ); \
+ if ( aError == KErrNone ) \
+ { \
+ aError = ___mtvObserverUtilsNotifyLoopError; \
+ } \
+ } \
+ else \
+ { \
+ existsNull = ETrue; \
+ } \
+ } \
+ RemoveNullObservers(existsNull, \
+ aObserverData); \
+ }\
+ } while (EFalse) \
+
+/**
+ * Adds an observer to an observer data object.
+ * @param aObserverData Data object to which an observer is added.
+ * @param aObserver Observer to add.
+ * @param aError Error code to use for Leave if adding fails.
+ */
+template <class ObserverType, class ContainerType>
+static void AddObserverL(ContainerType& aObserverData, ObserverType& aObserver, TInt aError)
+ {
+ if (aObserverData.iShutdown)
+ {
+ return;
+ }
+ TInt pos = aObserverData.iContainer.Find( &aObserver );
+ if (KErrNotFound != pos)
+ {
+ return;
+ }
+ TInt error = aObserverData.iContainer.Append( &aObserver );
+ if (KErrNone != error)
+ {
+ User::Leave(aError);
+ }
+ }
+
+/**
+ * Removes an observer from an observer data object.
+ * @param aObserverData Data object from which an observer is removed.
+ * @param aObserver Observer to remove.
+ */
+template <class ObserverType, class ContainerType>
+static void RemoveObserver( ContainerType& aObserverData, ObserverType& aObserver )
+ {
+ TInt pos = aObserverData.iContainer.Find( &aObserver );
+ if ( KErrNotFound == pos )
+ {
+ return;
+ }
+ if ( !aObserverData.iSemaphore )
+ {
+ // NotifyEventL is not part of call stack. Just remove.
+ aObserverData.iContainer.Remove( pos );
+ }
+ else
+ {
+ // Simply set to NULL. NotifyEventL will remove observers.
+ aObserverData.iContainer[ pos ] = NULL;
+ }
+ }
+
+} // end namespace MtvObserverUtils
+
+#endif //_MTV_OBSERVER_UTILS