--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/uiacceltk/hitchcock/ServerCore/Src/alfstreamerbridge.cpp Tue Feb 02 07:56:43 2010 +0200
@@ -0,0 +1,549 @@
+/*
+* 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: Interthread synchronization object
+*
+*/
+
+
+
+#include <e32debug.h>
+#include <coemain.h>
+#include "alfstreamerbridge.h"
+#include "alfstreamerserver.h"
+#include "alflogger.h"
+
+#ifdef ALF_DEBUG_TRACK_DRAWING
+#include "alfcommanddebug.h"
+#endif
+
+
+// #define EGL_TALKS_TO_WINDOW_SERVER
+
+// ---------------------------------------------------------------------------
+// constructor
+//
+// ---------------------------------------------------------------------------
+//
+
+// The priority is EActivePriorityWsEvents+1 instead of CActive::EPriorityHigh to prevent a deadlock
+// when AlfredServerThread calling iWsSession.GetEvent(event); from inside CCoeEnv::RunL() while
+// wserv was waiting inside CWindowServer::CDefaultAnimationScheduler::DoRedrawNow for Alf to
+// complete the TRequestStatus passed to CAlfRenderStage::End.
+
+CAlfStreamerBridge::CAlfStreamerBridge(MAlfStreamerListener* aObserver):CActive(EActivePriorityWsEvents+1),iObserver(aObserver), iBatchObserver(0), iThread(RThread().Id())
+ {
+ CActiveScheduler::Add(this);
+ iStatus = KRequestPending;
+ SetActive();
+ TInt err = iQueueSema.CreateLocal();
+
+ if (err)
+ {
+ // Device startup ends here.
+ __ALFLOGSTRING("Stop the music, we are running without synchronization");
+ User::Panic(_L("UI Accelerator"), 1);
+ }
+ }
+
+// ---------------------------------------------------------------------------
+// NewL
+//
+// ---------------------------------------------------------------------------
+//
+CAlfStreamerBridge* CAlfStreamerBridge::NewL( MAlfStreamerListener* aObserver )
+ {
+ CAlfStreamerBridge* self = new(ELeave)CAlfStreamerBridge( aObserver );
+ CleanupStack::PushL( self );
+ self->ConstructL();
+ CleanupStack::Pop( self );
+ return self;
+ }
+
+// ---------------------------------------------------------------------------
+// ConstructL
+//
+// ---------------------------------------------------------------------------
+//
+void CAlfStreamerBridge::ConstructL()
+ {
+ iDataBuf.Create( KInitialVariableBufferSize );
+ iDataBuf.SetLength(0);
+ iStreamerServer = NULL;
+#ifdef ALF_DEBUG_TRACK_DRAWING
+ iCommandDebugger = CAlfCommandDebug::NewL();
+#endif
+ CHuiEnv::Static()->iSwapObserver = this;
+ }
+
+// ---------------------------------------------------------------------------
+// destructor
+//
+// ---------------------------------------------------------------------------
+//
+CAlfStreamerBridge::~CAlfStreamerBridge()
+ {
+ CHuiEnv::Static()->iSwapObserver = 0;
+ iDataBuf.Close();
+ iQueueSema.Close();
+#ifdef ALF_DEBUG_TRACK_DRAWING
+ delete iCommandDebugger;
+#endif
+ }
+
+// ---------------------------------------------------------------------------
+// SetBatchObserver
+//
+// ---------------------------------------------------------------------------
+//
+void CAlfStreamerBridge::SetBatchObserver(MAlfBatchObs* aBatchObserver)
+ {
+ iBatchObserver = aBatchObserver;
+ }
+
+// ---------------------------------------------------------------------------
+// Activate
+//
+// ---------------------------------------------------------------------------
+//
+void CAlfStreamerBridge::Activate()
+ {
+ iStatus = KRequestPending;
+ SetActive();
+ }
+
+// ---------------------------------------------------------------------------
+// Trigger
+//
+// ---------------------------------------------------------------------------
+//
+TInt CAlfStreamerBridge::Trigger(TInt aStatus)
+ {
+ TInt err = KErrNone;
+ if (!iVarDataAddedButNotPosted)
+ {
+ iQueueSema.Wait();
+ }
+ iVarDataAddedButNotPosted = EFalse; // after this point, data may just be lost if posting fails
+ __ALFLOGSTRING2("CAlfStreamerBridge::Trigger status %d, own request status %d", aStatus, iStatus.Int() );
+ if (IsActive() && iStatus == KRequestPending)
+ {
+ RThread t;
+ TInt err = t.Open(iThread);
+ if (err)
+ {
+ __ALFLOGSTRING1( "CAlfStreamerBridge::Trigger() ignore RThread::Open() error: %d", err );
+ }
+ TRequestStatus* status = &iStatus;
+ __ALFLOGSTRING("CAlfStreamerBridge::Trigger - completing CAlfStreamerBridge");
+ t.RequestComplete(status, aStatus);
+ t.Close();
+ }
+ else
+ {
+#ifdef _DEBUG
+ if ( IsActive() )
+ {
+ __ALFLOGSTRING("CAlfStreamerBridge::Trigger - already active");
+ }
+ __ALFLOGSTRING("CAlfStreamerBridge::Trigger - appending data");
+#endif
+ err = iQueue.Append(aStatus);
+ }
+
+ iQueueSema.Signal();
+ __ALFLOGSTRING1("CAlfStreamerBridge::Trigger request status %d", iStatus.Int() );
+ return err;
+ }
+
+// ---------------------------------------------------------------------------
+// AddData
+//
+// ---------------------------------------------------------------------------
+//
+TInt CAlfStreamerBridge::AddData( TAlfDecoderServerBindings aOp,TInt aI1,TInt aI2 ,TAny* aPtr )
+ {
+ if (iSwapActive && aOp == EAlfRequestCommitBatch)
+ {
+ __ALFLOGSTRING("CAlfStreamerBridge::AddData() just release window server");
+ iBatchObserver->BridgerCallback(KRELEASEWINDOWSERVER,KRELEASEDBEFOREQUEUE);
+ return KErrNone;
+ }
+
+ TInt err = KErrNotFound;
+ {
+#ifdef ALF_DEBUG_TRACK_DRAWING
+ iCommandDebugger->SetDescription( aOp, R_ALF_BRIDGE_COMMAND_DESCRIPTION_ARRAY );
+ __ALFLOGSTRING2("CAlfStreamerBridge::AddData op %S, iQueue.Length = %d", &iCommandDebugger->Text(), iQueue.Count());
+ #else
+ __ALFLOGSTRING2("CAlfStreamerBridge::AddData op %d, iQueue.Length = %d", aOp, iQueue.Count());
+ #endif
+ err = KErrNone;
+ for(TInt i = 0; i < iMessages.Count(); i++ )
+ {
+ if (iMessages[i].IsEmpty())
+ {
+ iMessages[i].Set(aOp,aI1,aI2,aPtr);
+ err = Trigger(i);
+ return err;
+ }
+ }
+
+ // No existing (empty) cell was available for recycling, add new cell to array
+ TAlfBridgerData data;
+ data.Set(aOp,aI1,aI2,aPtr);
+ err = iMessages.Append(data);
+ }
+ if (!err)
+ {
+ err = Trigger(iMessages.Count()-1);
+ }
+ else
+ {
+ iQueueSema.Signal();
+ }
+ return err;
+ }
+
+// ---------------------------------------------------------------------------
+// GetData
+//
+// Note, that this method frees the message entry for reuse.
+// ---------------------------------------------------------------------------
+//
+TAlfBridgerData CAlfStreamerBridge::GetData(TInt aIndex)
+ {
+ TAlfBridgerData data;
+ ASSERT(aIndex <= iMessages.Count()-1);
+ data = iMessages[aIndex];
+ return data;
+ }
+
+void CAlfStreamerBridge::PrepareSwap()
+ {
+#ifdef EGL_TALKS_TO_WINDOW_SERVER
+ __ALFLOGSTRING("CAlfStreamerBridge:: Prepare swap, flush the queue");
+ iSwapActive = ETrue;
+ if (iStatus.Int() >=0 && iMessages.Count() > iStatus.Int() )
+ {
+ Cancel(); // remove from scheduler
+ RunL(); // run manually (and activate)
+ }
+ __ALFLOGSTRING("CAlfStreamerBridge:: Prepare swap, the queue emptied");
+#endif //#ifdef EGL_TALKS_TO_WINDOW_SERVER
+ }
+
+void CAlfStreamerBridge::SwapComplete()
+ {
+#ifdef EGL_TALKS_TO_WINDOW_SERVER
+ __ALFLOGSTRING("CAlfStreamerBridge:: Swap buffers complete");
+ iSwapActive = EFalse;
+#endif // #ifdef EGL_TALKS_TO_WINDOW_SERVER
+
+ }
+
+#ifdef EGL_TALKS_TO_WINDOW_SERVER
+void CAlfStreamerBridge::ReleaseWindowServer(TBool aRelease)
+ {
+ __ALFLOGSTRING1("CAlfStreamerBridge::ReleaseWindowServer: %d",aRelease);
+ if (aRelease)
+ {
+ iMakeCurrentActive = ETrue;
+ if (iBatchObserver && !iSwapActive)
+ {
+ iBatchObserver->BridgerCallback(KRELEASEWINDOWSERVER);
+ }
+ }
+ else
+ {
+ iMakeCurrentActive = EFalse;
+ }
+#else
+void CAlfStreamerBridge::ReleaseWindowServer(TBool)
+ {
+#endif
+ }
+
+void CAlfStreamerBridge::SetWgIdArray(TInt* aArray)
+ {
+ iWgArray = aArray;
+ }
+
+EXPORT_C TUid CAlfStreamerBridge::FindAppUidForWgId(TInt aWgId)
+ {
+ if (iWgArray)
+ {TInt* ptr = iWgArray;
+ for (TInt i=0; i<39; i=i+2) // magic
+ {
+ if (ptr[i] == aWgId)
+ {
+ return TUid::Uid(ptr[i+1]);
+ }
+ if (!ptr[i])
+ {
+ break;
+ }
+ }
+ }
+ return KNullUid;
+ }
+
+EXPORT_C TInt CAlfStreamerBridge::FindWgForAppUid(TUid aAppUid)
+ {
+ if (iWgArray)
+ {TInt* ptr = iWgArray;
+ for (TInt i=0; i<39; i=i+2) // magic
+ {
+ if (ptr[i+1] == aAppUid.iUid)
+ {
+ return ptr[i];
+ }
+ if (!ptr[i])
+ {
+ break;
+ }
+ }
+ }
+ return 0;
+ }
+
+// ---------------------------------------------------------------------------
+// RunL
+//
+// ---------------------------------------------------------------------------
+//
+void CAlfStreamerBridge::RunL()
+ {
+ TInt operation = iMessages[iStatus.Int()].iOp;
+
+#ifdef ALF_DEBUG_TRACK_DRAWING
+ iCommandDebugger->SetDescription( operation, R_ALF_BRIDGE_COMMAND_DESCRIPTION_ARRAY );
+ __ALFLOGSTRING1("CAlfStreamerBridge::RunL: First op %S", &iCommandDebugger->Text() );
+#else
+ __ALFLOGSTRING1("CAlfStreamerBridge::RunL: First op %d", operation);
+#endif
+ switch ( operation )
+ {
+ // Just call back to Alf decoder thread
+ case EAlfRequestCommitBatch:
+ case EAlfRequestCommandReadNotification:
+ case EAlfReleaseTemporaryChunk:
+ {
+ if (iBatchObserver)
+ {
+ iBatchObserver->BridgerCallback( operation, iMessages[iStatus.Int()].iInt1 );
+ }
+ iMessages[iStatus.Int()].ResetEntry();
+ break;
+ }
+ default:
+ {
+ // Handle command
+ __ALFLOGSTRING("CAlfStreamerBridge:: calling observer callback");
+ iObserver->HandleCallback(iStatus.Int());
+
+ // For "getters" also call back to Alf decoder thread
+ if ((operation > EAlfDSGetCommandsStart) && (operation < EAlfDSGetCommandsEnd))
+ {
+ if (iBatchObserver)
+ {
+ iBatchObserver->BridgerCallback( operation, iMessages[iStatus.Int()].iInt1 );
+ }
+ }
+
+ iMessages[iStatus.Int()].ResetEntry(); // mark the cell free
+ }
+ }
+
+ // Todo: is this kind of burst mode ok, it should be..
+ iQueueSema.Wait();
+ while (iQueue.Count())
+ {
+ TInt operation2 = iMessages[iQueue[0]].iOp;
+#ifdef ALF_DEBUG_TRACK_DRAWING
+ iCommandDebugger->SetDescription( operation2, R_ALF_BRIDGE_COMMAND_DESCRIPTION_ARRAY );
+ __ALFLOGSTRING1("CAlfStreamerBridge:: Queue op %S", &iCommandDebugger->Text() );
+#else
+ __ALFLOGSTRING1("CAlfStreamerBridge:: Queue op %d", operation2 );
+#endif
+ switch ( operation2 )
+ {
+ case EAlfRequestCommitBatch:
+ case EAlfRequestCommandReadNotification:
+ case EAlfReleaseTemporaryChunk:
+ {
+ if (iBatchObserver)
+ {
+ __ALFLOGSTRING("CAlfStreamerBridge:: calling BATCH observer callback");
+ iBatchObserver->BridgerCallback( operation2, iMessages[iQueue[0]].iInt1 );
+ }
+ iMessages[iQueue[0]].ResetEntry();
+ break;
+ }
+ default:
+ {
+ // Handle command
+ __ALFLOGSTRING("CAlfStreamerBridge:: calling observer callback");
+ iObserver->HandleCallback(iQueue[0]);
+
+ // For "getters" also call back to Alf decoder thread
+ if ((operation2 > EAlfDSGetCommandsStart) && (operation2 < EAlfDSGetCommandsEnd))
+ {
+ if (iBatchObserver)
+ {
+ iBatchObserver->BridgerCallback( operation2, iMessages[iQueue[0]].iInt1 );
+ }
+ }
+ iMessages[iQueue[0]].ResetEntry(); // mark the cell free
+ }
+ }
+ iQueue.Remove(0);
+ }
+ if ( !iItemsInBuffer )
+ {
+ iDataBuf.SetLength(0);
+ }
+
+ __ALFLOGSTRING1("CAlfStreamerBridge::RunL - activating", iItemsInBuffer);
+ Activate();
+ iQueueSema.Signal();
+ __ALFLOGSTRING1("CAlfStreamerBridge::RunL - really really ending", iItemsInBuffer);
+ }
+
+// ---------------------------------------------------------------------------
+// DoCancel
+//
+// ---------------------------------------------------------------------------
+//
+void CAlfStreamerBridge::DoCancel()
+ {
+ if (iBatchObserver)
+ {
+ iBatchObserver->BridgerCanceled();
+ }
+ }
+
+// ---------------------------------------------------------------------------
+// StartNewBlock
+//
+// ---------------------------------------------------------------------------
+//
+void CAlfStreamerBridge::StartNewBlock()
+ {
+ // Queue marker. Basically we could use one new member to assert that there can
+ // be only one marker
+ __ALFLOGSTRING1("CAlfStreamerBridge:: Request command read notification, swap active: %d", iSwapActive );
+ if ( iSwapActive || iMakeCurrentActive )
+ {
+ __ALFLOGSTRING("CAlfStreamerBridge::StartNewBlock() just release window server");
+ iBatchObserver->BridgerCallback(KRELEASEWINDOWSERVER,KRELEASEDBEFOREQUEUE);
+ return;
+ }
+ AddData(EAlfRequestCommitBatch,0,0,0);
+ }
+
+// ---------------------------------------------------------------------------
+// RequestCommandReadNotification
+//
+// ---------------------------------------------------------------------------
+//
+void CAlfStreamerBridge::RequestCommandReadNotification( TInt aLastReadOffset, TAlfDecoderServerBindings aCommand )
+ {
+ AddData( aCommand, aLastReadOffset, 0, 0);
+ }
+
+// ---------------------------------------------------------------------------
+// AppendVarDataL
+//
+// Note, that memory allocation is done only if current buffer is not large enough
+// to add an item.
+// TODO: The buffers added are not the buffer in optimal way.
+// ---------------------------------------------------------------------------
+//
+EXPORT_C const TAny* CAlfStreamerBridge::AppendVarDataL( TInt aSize, TInt& aIndex )
+ {
+ iQueueSema.Wait();
+ // Make sure the length of the allocated data is always divisible by 8
+ if ( aSize % 8 != 0 )
+ {
+ __ALFLOGSTRING1("CAlfStreamerBridge::AppendVarDataL, size not multiple of 8: %d", aSize );
+ aSize = aSize + ( 8 - aSize % 8 );
+ }
+ if ( iDataBuf.Length() + aSize >= iDataBuf.MaxLength() )
+ {
+ TRAPD(err, iDataBuf.ReAllocL( iDataBuf.MaxLength() + KInitialVariableBufferSize ));
+ if ( err )
+ {
+ __ALFLOGSTRING("CAlfStreamerBridge::AppendVarDataL, realloc failed");
+ iQueueSema.Signal();
+ return NULL;
+ }
+ __ALFLOGSTRING1("CAlfStreamerBridge::AppendVarDataL, new max size: %d", iDataBuf.MaxLength() );
+ }
+ aIndex = iDataBuf.Length();
+ iDataBuf.SetLength( iDataBuf.Length() + aSize);
+ iItemsInBuffer++;
+ __ALFLOGSTRING1("CAlfStreamerBridge::AppendVarDataL: buflength %d", iDataBuf.Length());
+ iVarDataAddedButNotPosted = ETrue;
+ return iDataBuf.MidTPtr( aIndex ).Ptr();
+ }
+
+// ---------------------------------------------------------------------------
+// GetVarDataL
+//
+// Note, that data is not removed at any point. However it should not be accessed again
+// with this method, because that would confuse iItemsInBuffer counter.
+// ---------------------------------------------------------------------------
+//
+const TAny* CAlfStreamerBridge::GetVarDataL( TInt aIndex )
+ {
+ ASSERT( aIndex >= 0 && aIndex < iDataBuf.MaxLength() );
+ ASSERT( iItemsInBuffer );
+ iItemsInBuffer--;
+ return iDataBuf.MidTPtr( aIndex ).Ptr();
+ }
+
+EXPORT_C const TAny* CAlfStreamerBridge::AppendEffectsDataL( TInt aSize, TInt& aIndex )
+ {
+ return AppendVarDataL( aSize, aIndex );
+ }
+
+// ---------------------------------------------------------------------------
+// GetVarDataL
+//
+// Note, that data is not removed at any point. However it should not be accessed again
+// with this method, because that would confuse iItemsInBuffer counter.
+// ---------------------------------------------------------------------------
+//
+const TAny* CAlfStreamerBridge::GetEffectsDataL( TInt aIndex )
+ {
+ return GetVarDataL(aIndex);
+ }
+
+// ---------------------------------------------------------------------------
+// SetStreamerServer
+// ---------------------------------------------------------------------------
+//
+void CAlfStreamerBridge::SetStreamerServer( CAlfStreamerServer& aStreamerServer )
+ {
+ iStreamerServer = &aStreamerServer;
+ }
+
+// ---------------------------------------------------------------------------
+// StreamerServer
+// ---------------------------------------------------------------------------
+//
+CAlfStreamerServer* CAlfStreamerBridge::StreamerServer()
+ {
+ return iStreamerServer;
+ }