diff src/main/symbian/EKA2/SDL_main.cpp @ 3975:e85e65aec22f SDL-1.2

Added S60 port.
author Ryan C. Gordon <icculus@icculus.org>
date Sun, 24 Jun 2007 18:26:35 +0000
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/main/symbian/EKA2/SDL_main.cpp	Sun Jun 24 18:26:35 2007 +0000
@@ -0,0 +1,1035 @@
+/*
+    SDL_Main.cpp
+    Symbian OS services for SDL
+
+    Markus Mertama
+*/
+
+
+#include "epoc_sdl.h"
+
+#include"sdlepocapi.h"
+#include <e32base.h>
+#include <estlib.h>
+#include <stdio.h>
+#include <badesca.h>
+
+#include "vectorbuffer.h"
+#include <w32std.h>
+#include <aknappui.h>
+#include <aknapp.h>
+#include "SDL_epocevents_c.h"
+#include "SDL_keysym.h"
+#include "dsa.h"
+
+
+#ifdef SYMBIANC
+#include <reent.h>
+#endif
+
+//Markus Mertama
+
+
+extern SDLKey* KeyMap();
+extern void ResetKeyMap();
+
+class CCurrentAppUi;
+
+//const TUid KSDLUid =  { 0xF01F3D69 };
+
+NONSHARABLE_CLASS(EnvUtils)
+	{
+	public:
+	static void DisableKeyBlocking();
+	static TBool Rendezvous(RThread& aThread, TRequestStatus& aStatus);
+	};
+
+TInt Panic(TInt aErr, TInt aLine)
+	{
+	TBuf<64> b;
+	b.Format(_L("Main at %d"), aLine);
+	User::Panic(b, aErr);
+	return 0;	
+	}
+	
+
+NONSHARABLE_CLASS(CCurrentAppUi) : public CAknAppUi
+	{
+	public:
+	static CCurrentAppUi* Cast(CEikAppUi* aUi);
+	void DisableKeyBlocking();
+	};
+	
+	
+CCurrentAppUi* CCurrentAppUi::Cast(CEikAppUi* aUi)
+	{
+	return static_cast<CCurrentAppUi*>(aUi);	
+	}
+	
+void CCurrentAppUi::DisableKeyBlocking()	
+	{
+	SetKeyBlockMode(ENoKeyBlock);	
+	}
+
+
+class CEventQueue : public CBase, public MEventQueue
+    {
+    public:
+        static CEventQueue* NewL();
+        ~CEventQueue();
+    public:
+        TInt Append(const TWsEvent& aEvent);
+       	const TWsEvent& Shift();
+       	void Lock();
+       	void Unlock();
+        TBool HasData();
+    private:
+        TVector<TWsEvent, 64> iVector;
+        RCriticalSection iCS;
+    };
+    
+ CEventQueue* CEventQueue::NewL()
+    {
+    CEventQueue* q = new (ELeave) CEventQueue();
+    CleanupStack::PushL(q);
+    User::LeaveIfError(q->iCS.CreateLocal());
+    CleanupStack::Pop();
+    return q;
+    }
+    
+CEventQueue::~CEventQueue()
+    {
+    iCS.Close();
+    }
+    
+TInt CEventQueue::Append(const TWsEvent& aEvent)
+    {
+    iCS.Wait();
+   	const TInt err = iVector.Append(aEvent);
+    iCS.Signal();
+    return err;
+    }
+    
+    
+TBool CEventQueue::HasData()
+    {
+    return iVector.Size() > 0;
+    }
+
+
+void CEventQueue::Lock()
+	{
+    iCS.Wait();
+	}
+	
+void CEventQueue::Unlock()
+	{
+	iCS.Signal();
+	}
+
+const TWsEvent& CEventQueue::Shift()
+    {
+    const TWsEvent& event =  iVector.Shift();
+    return event;
+    }
+
+
+TSdlCleanupItem::TSdlCleanupItem(TSdlCleanupOperation aOperation, TAny* aItem) :
+iOperation(aOperation), iItem(aItem), iThread(RThread().Id())
+    {
+    }
+
+class CEikonEnv;
+class CSdlAppServ;
+
+    
+NONSHARABLE_CLASS(EpocSdlEnvData)
+    {
+    public:
+    void Free();
+    CEventQueue*            iEventQueue;
+    TMainFunc				iMain;
+    TInt            		iEpocEnvFlags;
+    int                     iArgc;
+    char**                  iArgv;
+    CDsa*                   iDsa;
+    CSdlAppServ*            iAppSrv;
+    TThreadId               iId;
+    CArrayFix<TSdlCleanupItem>* iCleanupItems; 
+    CEikAppUi*				iAppUi;
+    CSDL*					iSdl;
+    };
+  
+   
+EpocSdlEnvData* gEpocEnv;
+
+#define MAINFUNC(x) EXPORT_C TMainFunc::TMainFunc(mainfunc##x aFunc){Mem::FillZ(iMainFunc, sizeof(iMainFunc)); iMainFunc[x - 1] = (void*) aFunc;}
+    
+MAINFUNC(1)
+MAINFUNC(2)
+MAINFUNC(3)
+MAINFUNC(4)
+MAINFUNC(5)
+MAINFUNC(6)
+
+EXPORT_C TMainFunc::TMainFunc() 
+	{
+	Mem::FillZ(iMainFunc, sizeof(iMainFunc));
+	}
+	
+
+const void* TMainFunc::operator[](TInt aIndex) const
+	{
+	return iMainFunc[aIndex];
+	}
+
+
+NONSHARABLE_CLASS(CSdlAppServ) : public CActive
+    {
+    public:
+        enum
+            {
+            EAppSrvNoop = CDsa::ELastDsaRequest,
+            EAppSrvWindowWidth,
+            EAppSrvWindowHeight,
+            EAppSrvWindowDisplayMode,
+            EAppSrvWindowPointerCursorMode,
+            EAppSrvDsaStatus,
+            EAppSrvStopThread,
+            EAppSrvWaitDsa
+            };
+        CSdlAppServ();
+        void ConstructL();
+        ~CSdlAppServ();
+        TInt Request(TInt aService);
+        TInt RequestValue(TInt aService);
+        void Init(); 
+        void PanicMain(TInt aReason);
+        void PanicMain(const TDesC& aInfo, TInt aReason);
+        void SetObserver(MSDLObserver* aObserver);
+        TInt ObserverEvent(TInt aEvent, TInt aParam);
+        void SetParam(TInt aParam);
+        void HandleObserverValue(TInt aService, TInt aReturnValue, TBool aMainThread);
+        MSDLObserver* Observer();
+    private:
+        void RunL();
+        void DoCancel();
+    private:
+        const TThreadId iMainId;
+        RThread iAppThread;
+        TInt iService;
+        TInt iReturnValue;
+        RSemaphore iSema;
+        MSDLObserver* iObserver;
+        TRequestStatus* iStatusPtr;
+    };
+    
+CSdlAppServ::CSdlAppServ() : CActive(CActive::EPriorityHigh), iMainId(RThread().Id())
+    {
+    }
+    
+    
+    
+MSDLObserver* CSdlAppServ::Observer()
+	{
+	return iObserver;
+	}
+	
+	
+void CSdlAppServ::SetObserver(MSDLObserver* aObserver)
+	{
+	iObserver = aObserver;
+	}	
+	
+TInt CSdlAppServ::ObserverEvent(TInt aEvent, TInt aParam)
+	{
+	if(iObserver != NULL)
+		{
+		if(RThread().Id() == gEpocEnv->iId)
+			{
+			return iObserver->SdlThreadEvent(aEvent, aParam);
+			}
+		else if(RThread().Id() == iMainId)
+			{
+			return iObserver->SdlEvent(aEvent, aParam);
+			}
+		PANIC(KErrNotSupported);
+		}
+	return 0;
+	}
+	
+void CSdlAppServ::PanicMain(TInt aReason)    
+    {
+    iAppThread.Panic(RThread().Name(), aReason);
+    }
+    
+void CSdlAppServ::PanicMain(const TDesC& aInfo, TInt aReason)    
+    {
+    iAppThread.Panic(aInfo, aReason);
+    }    
+    
+void CSdlAppServ::ConstructL()
+    {
+    CActiveScheduler::Add(this);
+    User::LeaveIfError(iSema.CreateLocal(1));
+    iStatus = KRequestPending;
+    iStatusPtr = &iStatus;
+    SetActive();
+    }
+        
+ CSdlAppServ::~CSdlAppServ()
+    {
+    Cancel();
+    if(iSema.Handle() != NULL)
+        iSema.Signal();
+    iSema.Close();
+    iAppThread.Close();
+    }
+    
+TInt CSdlAppServ::Request(TInt aService)
+    {
+    if(RThread().Id() != iAppThread.Id())
+    	{
+    	iSema.Wait();
+    	iService = aService;
+    	iAppThread.RequestComplete(iStatusPtr, KErrNone); 
+    	return KErrNone;
+    	}
+    return KErrBadHandle;
+    }
+    
+TInt CSdlAppServ::RequestValue(TInt aService)
+    {
+    Request(aService);
+    Request(EAppSrvNoop);
+    return iReturnValue;
+    }
+   
+void CSdlAppServ::Init()
+    {
+    PANIC_IF_ERROR(iAppThread.Open(iMainId));
+    }
+
+void CSdlAppServ::SetParam(TInt aParam)
+	{
+	iReturnValue = aParam;
+	}
+	
+void CSdlAppServ::HandleObserverValue(TInt aService, TInt aReturnValue, TBool aMainThread)
+	{
+	if(iObserver != NULL && aMainThread)
+		{
+		switch(aService)
+			{
+			case MSDLObserver::EEventScreenSizeChanged:
+			if(aReturnValue == MSDLObserver::EScreenSizeChangedDefaultPalette)
+				EpocSdlEnv::LockPalette(EFalse);
+			break;
+			}
+		}
+	if(!aMainThread && aService == MSDLObserver::EEventSuspend)
+		{
+		if(iObserver == NULL || 
+		(gEpocEnv->iDsa->Stopped() && aReturnValue != MSDLObserver::ESuspendNoSuspend))
+			{
+			EpocSdlEnv::Suspend();
+			}
+		}
+	}
+
+void CSdlAppServ::RunL()
+    {
+    if(iStatus == KErrNone)
+        {
+        switch(iService)
+            {
+            case CSdlAppServ::EAppSrvWaitDsa:
+            	EpocSdlEnv::SetWaitDsa();
+            	iReturnValue = EpocSdlEnv::IsDsaAvailable();
+            //		}
+            //	gEpocEnv->iDsa->Stop();
+            //	gEpocEnv->iDsa->RestartL();
+            	break;
+           	 case CSdlAppServ::EAppSrvStopThread:
+            	gEpocEnv->iDsa->SetSuspend();
+            	break;
+            case EpocSdlEnv::EDisableKeyBlocking:
+                EnvUtils::DisableKeyBlocking();
+                break;
+          
+            case EAppSrvWindowPointerCursorMode:
+                iReturnValue = gEpocEnv->iDsa != NULL ?
+                 gEpocEnv->iDsa->Session().PointerCursorMode() : KErrNotReady; 
+                break;
+            case EAppSrvDsaStatus:
+            	gEpocEnv->iDsa->Stop();
+                iReturnValue = KErrNone;
+                break;
+            case CDsa::ERequestUpdate:
+            	gEpocEnv->iDsa->UnlockHWSurfaceRequestComplete();
+            	break;
+            case EAppSrvNoop:
+                break;
+            case MSDLObserver::EEventResume:
+            case MSDLObserver::EEventSuspend:
+            case MSDLObserver::EEventScreenSizeChanged:
+            case MSDLObserver::EEventWindowReserved:
+            case MSDLObserver::EEventKeyMapInit:
+            case MSDLObserver::EEventWindowNotAvailable:
+            case MSDLObserver::EEventMainExit:
+            	iReturnValue = ObserverEvent(iService, iReturnValue);
+            	HandleObserverValue(iService, iReturnValue, ETrue);
+            	break;
+            default:
+                PANIC(KErrNotSupported);
+            }
+        iStatus = KRequestPending;
+        iStatusPtr = &iStatus;
+        SetActive();
+        }
+    iSema.Signal();
+    }
+    
+void CSdlAppServ::DoCancel()
+    {
+    iSema.Wait();
+    TRequestStatus* s = &iStatus;
+    iAppThread.RequestComplete(s, KErrCancel); 
+    }
+ 
+
+
+MEventQueue& EpocSdlEnv::EventQueue()
+    {
+    __ASSERT_DEBUG(gEpocEnv != NULL, PANIC(KErrNotReady));
+    return *gEpocEnv->iEventQueue;
+    }
+
+
+TBool EpocSdlEnv::Flags(TInt aFlag)
+    {
+	const TInt flag = gEpocEnv->iEpocEnvFlags & aFlag;
+	return flag == aFlag;
+    }
+
+TInt EpocSdlEnv::Argc()
+    {
+    __ASSERT_DEBUG(gEpocEnv != NULL, PANIC(KErrNotReady));
+    return gEpocEnv->iArgc;
+    }
+    
+    
+char** EpocSdlEnv::Argv()
+    {
+    __ASSERT_DEBUG(gEpocEnv != NULL, PANIC(KErrNotReady));
+    return gEpocEnv->iArgv;
+    }
+    
+    
+TBool EpocSdlEnv::IsDsaAvailable()
+    {
+    __ASSERT_DEBUG(gEpocEnv != NULL, PANIC(KErrNotReady));
+    return gEpocEnv->iDsa != NULL && gEpocEnv->iDsa->IsDsaAvailable();
+    }
+
+  
+void EpocSdlEnv::WaitDsaAvailable()
+	{
+	EpocSdlEnv::ObserverEvent(MSDLObserver::EEventWindowNotAvailable, 0);
+	gEpocEnv->iAppSrv->Request(CSdlAppServ::EAppSrvStopThread);
+	if(EpocSdlEnv::Flags(CSDL::EEnableFocusStop))
+		{
+		EpocSdlEnv::ObserverEvent(MSDLObserver::EEventSuspend, 0);
+		}
+	}
+	
+void EpocSdlEnv::Suspend()
+	{
+	if(gEpocEnv->iDsa->Stopped() || EpocSdlEnv::Flags(CSDL::EEnableFocusStop))
+		{
+	//	gEpocEnv->iDsa->ReleaseStop(); 
+		gEpocEnv->iDsa->SetSuspend(); 
+		RThread().Suspend();
+		EpocSdlEnv::ObserverEvent(MSDLObserver::EEventResume, 0);
+		}
+	}
+	
+void EpocSdlEnv::SetWaitDsa()
+	{
+	if(!IsDsaAvailable())
+		{
+		RThread th;
+		th.Open(gEpocEnv->iId);
+		th.Suspend();
+		th.Close();
+		gEpocEnv->iDsa->SetSuspend(); 
+		}
+	}
+	
+void EpocSdlEnv::Resume()
+	{
+	gEpocEnv->iDsa->Resume();
+	RThread th;
+	th.Open(gEpocEnv->iId);
+	th.Resume();
+	th.Close();
+	
+	const TInt value = gEpocEnv->iAppSrv->ObserverEvent(MSDLObserver::EEventResume, 0);
+	gEpocEnv->iAppSrv->HandleObserverValue(MSDLObserver::EEventResume, value, ETrue);
+	}
+    
+
+TInt EpocSdlEnv::AllocSwSurface(const TSize& aSize, TDisplayMode aMode)
+	{
+	return gEpocEnv->iDsa->AllocSurface(EFalse, aSize, aMode);
+	}
+	
+TInt EpocSdlEnv::AllocHwSurface(const TSize& aSize, TDisplayMode aMode)
+	{
+	return gEpocEnv->iDsa->AllocSurface(ETrue, aSize, aMode);
+	}
+		
+	
+void EpocSdlEnv::UnlockHwSurface()
+	{
+	gEpocEnv->iDsa->UnlockHwSurface();
+	}
+	
+TUint8* EpocSdlEnv::LockHwSurface()
+	{
+	return gEpocEnv->iDsa->LockHwSurface();
+	}
+
+
+void EpocSdlEnv::UpdateSwSurface()
+	{
+	gEpocEnv->iDsa->UpdateSwSurface();
+	}
+	
+TBool EpocSdlEnv::AddUpdateRect(TUint8* aAddress, const TRect& aUpdateRect, const TRect& aRect)
+	{
+	return gEpocEnv->iDsa->AddUpdateRect(aAddress, aUpdateRect, aRect);
+	}
+	
+void EpocSdlEnv::Request(TInt aService)
+    {
+    __ASSERT_DEBUG(gEpocEnv != NULL, PANIC(KErrNotReady));
+    gEpocEnv->iAppSrv->Request(aService);
+    }
+    
+    
+TSize EpocSdlEnv::WindowSize(const TSize& aRequestedSize)
+    { 
+    __ASSERT_DEBUG(gEpocEnv != NULL, PANIC(KErrNotReady));
+    if(EpocSdlEnv::Flags(CSDL::EAllowImageResize) && gEpocEnv->iDsa->WindowSize() != aRequestedSize)
+    	{
+    	TRAP_IGNORE(gEpocEnv->iDsa->CreateZoomerL(aRequestedSize));
+    	}
+    return gEpocEnv->iDsa->WindowSize();
+    }
+    
+ TSize EpocSdlEnv::WindowSize()
+    { 
+    __ASSERT_DEBUG(gEpocEnv != NULL, PANIC(KErrNotReady));
+    return gEpocEnv->iDsa->WindowSize();
+    }   
+    
+TDisplayMode EpocSdlEnv::DisplayMode()
+    {
+    return gEpocEnv->iDsa->DisplayMode();
+    }
+    
+TPointerCursorMode EpocSdlEnv::PointerMode()
+    {
+    return static_cast<TPointerCursorMode>
+    (gEpocEnv->iAppSrv->RequestValue(CSdlAppServ::EAppSrvWindowPointerCursorMode));
+    }
+    
+TInt EpocSdlEnv::SetPalette(TInt aFirstcolor, TInt aColorCount, TUint32* aPalette)  
+	{
+	return 	gEpocEnv->iDsa->SetPalette(aFirstcolor, aColorCount, aPalette);
+	}
+
+void EpocSdlEnv::PanicMain(TInt aErr)
+    {
+    gEpocEnv->iAppSrv->PanicMain(aErr);
+    }
+    
+    
+TInt EpocSdlEnv::AppendCleanupItem(const TSdlCleanupItem& aItem)
+    {
+    TRAPD(err, gEpocEnv->iCleanupItems->AppendL(aItem));
+    return err;
+    }
+    
+void EpocSdlEnv::RemoveCleanupItem(TAny* aItem)
+    {
+    for(TInt i = 0; i < gEpocEnv->iCleanupItems->Count(); i++)
+        {
+        if(gEpocEnv->iCleanupItems->At(i).iItem == aItem)
+            gEpocEnv->iCleanupItems->Delete(i);
+        }
+    }
+    
+void EpocSdlEnv::CleanupItems()     
+	{
+	const TThreadId id = RThread().Id();
+	TInt last = gEpocEnv->iCleanupItems->Count() - 1;
+	TInt i;
+	for(i = last; i >= 0 ; i--)
+        {
+        TSdlCleanupItem& item = gEpocEnv->iCleanupItems->At(i);
+        if(item.iThread == id)
+        	{
+        	item.iThread = TThreadId(0); 
+        	item.iOperation(item.iItem);
+        	}
+        }
+    last = gEpocEnv->iCleanupItems->Count() - 1;
+	for(i = last; i >= 0 ; i--)
+        {
+        TSdlCleanupItem& item = gEpocEnv->iCleanupItems->At(i);
+        if(item.iThread == TThreadId(0))
+        	{
+        	gEpocEnv->iCleanupItems->Delete(i);
+        	}
+        }
+	}
+	
+void EpocSdlEnv::FreeSurface()
+	{
+	Request(CSdlAppServ::EAppSrvDsaStatus);
+	gEpocEnv->iDsa->Free();
+	}
+  
+void EpocSdlEnv::LockPalette(TBool aLock)
+	{
+	gEpocEnv->iDsa->LockPalette(aLock);
+	}
+    
+void EpocSdlEnv::ObserverEvent(TInt aService, TInt aParam)
+	{
+	const TBool sdlThread = RThread().Id() == gEpocEnv->iId;
+	const TInt valuea = gEpocEnv->iAppSrv->ObserverEvent(aService, aParam);
+	gEpocEnv->iAppSrv->HandleObserverValue(aService, valuea, !sdlThread);
+	if(sdlThread)
+		{
+		gEpocEnv->iAppSrv->SetParam(aParam);
+		const TInt valuet = gEpocEnv->iAppSrv->RequestValue(aService);
+		gEpocEnv->iAppSrv->HandleObserverValue(aService, valuet, EFalse);	
+		}
+	}
+			
+    
+TPoint EpocSdlEnv::WindowCoordinates(const TPoint& aPoint)    
+    {
+    return gEpocEnv->iDsa->WindowCoordinates(aPoint);	
+    }
+    
+void EpocSdlEnv::PanicMain(const TDesC& aInfo, TInt aErr)
+    {
+    gEpocEnv->iAppSrv->PanicMain(aInfo, aErr);
+    }
+//Dsa is a low priority ao, it has to wait if its pending event, but ws
+//event has been prioritized before it
+//this is not called from app thread!
+void EpocSdlEnv::WaitDeviceChange() 
+    {
+  	LockPalette(ETrue);
+    gEpocEnv->iAppSrv->RequestValue(CSdlAppServ::EAppSrvWaitDsa);
+    const TSize sz = WindowSize();
+    const TInt param = reinterpret_cast<TInt>(&sz);
+    ObserverEvent(MSDLObserver::EEventScreenSizeChanged, param);
+    	
+   // RThread().Suspend();
+    }  
+    
+LOCAL_C TBool CheckSdl() 
+    {
+    TInt isExit = ETrue;
+    RThread sdl;
+    if(sdl.Open(gEpocEnv->iId) == KErrNone)
+        {
+        if(sdl.ExitType() == EExitPending)
+            {
+            isExit = EFalse;
+            }
+        sdl.Close();
+        }
+    return isExit;
+    }
+    
+void EpocSdlEnvData::Free()
+    {
+    if(RThread().Id() == gEpocEnv->iId)
+    	{
+    	iDsa->Free();
+    	return;
+    	}
+   
+    __ASSERT_ALWAYS(iArgv == NULL || CheckSdl(), PANIC(KErrNotReady));
+        
+    for(TInt i = 0; i < iArgc; i++)
+        User::Free( iArgv[i] );
+        
+    User::Free(iArgv);	
+     
+    
+    delete iEventQueue;
+    
+    if(iDsa != NULL)
+    	iDsa->Free();
+    
+	delete iDsa;
+	delete iAppSrv;
+    }
+
+_LIT(KSDLMain, "SDLMain");
+
+LOCAL_C int MainL()
+    {
+    gEpocEnv->iCleanupItems = new (ELeave) CArrayFixFlat<TSdlCleanupItem>(8);
+    
+    char** envp=0;
+     /* !! process exits here if there is "exit()" in main! */
+    int ret = 0;
+    for(TInt i = 0; i  < 6; i++)
+        {
+        void* f = (void*) gEpocEnv->iMain[i];
+        if(f != NULL)
+            {
+            switch(i)
+                {
+                case 0:
+                    ret = ((mainfunc1)f)(); 
+                    return ret;
+                case 3:
+                    ((mainfunc1)f)(); 
+                    return ret;
+                case 1:
+                    ret = ((mainfunc2)f)(EpocSdlEnv::Argc(), EpocSdlEnv::Argv());
+                    return ret;
+                case 4:
+                    ((mainfunc2)f)(EpocSdlEnv::Argc(), EpocSdlEnv::Argv());
+                    return ret;
+                case 2:
+                    ret = ((mainfunc3)f)(EpocSdlEnv::Argc(), EpocSdlEnv::Argv(), envp);
+                    return ret;
+                case 5:
+                    ((mainfunc3)f)(EpocSdlEnv::Argc(), EpocSdlEnv::Argv(), envp);
+                    return ret;
+                }
+            }
+        }
+    PANIC(KErrNotFound);
+    return 0;
+    }
+
+LOCAL_C TInt DoMain(TAny* /*aParam*/)
+    {
+    
+    
+    CTrapCleanup* cleanup = CTrapCleanup::New();
+      	
+	TBool fbsconnected = EFalse;
+	if(RFbsSession::GetSession() == NULL)
+	    {
+	    PANIC_IF_ERROR(RFbsSession::Connect());
+	    fbsconnected = ETrue;
+	    }
+	
+ 	gEpocEnv->iAppSrv->Init();	
+
+#ifdef SYMBIANC 
+    // Create stdlib 
+    _REENT;
+#endif
+
+    // Call stdlib main
+    int ret = 0;
+    
+    //completes waiting rendesvous
+    RThread::Rendezvous(KErrNone);
+    
+    TRAPD(err, err = MainL());
+    
+    EpocSdlEnv::ObserverEvent(MSDLObserver::EEventMainExit, err);
+   
+    // Free resources and return
+    
+  	EpocSdlEnv::CleanupItems();
+        
+    gEpocEnv->iCleanupItems->Reset();
+    delete gEpocEnv->iCleanupItems;
+    gEpocEnv->iCleanupItems = NULL;
+    
+    gEpocEnv->Free(); //free up in thread resources 
+    
+#ifdef SYMBIANC    
+    _cleanup(); //this is normally called at exit, I call it here
+#endif
+
+    if(fbsconnected)
+        RFbsSession::Disconnect();
+    
+#ifdef SYMBIANC     
+    CloseSTDLIB();
+#endif
+       
+ //   delete as;
+   	delete cleanup;	
+
+    return err == KErrNone ? ret : err;;
+    }
+    
+
+    
+EXPORT_C CSDL::~CSDL()
+    {
+   	gEpocEnv->Free();
+    User::Free(gEpocEnv);
+    gEpocEnv->iSdl = NULL;
+    }
+
+EXPORT_C CSDL* CSDL::NewL(TInt aFlags)
+    {
+    __ASSERT_ALWAYS(gEpocEnv == NULL, PANIC(KErrAlreadyExists));
+    gEpocEnv = (EpocSdlEnvData*) User::AllocL(sizeof(EpocSdlEnvData));
+    Mem::FillZ(gEpocEnv, sizeof(EpocSdlEnvData));
+   
+    gEpocEnv->iEpocEnvFlags = aFlags;
+    gEpocEnv->iEventQueue = CEventQueue::NewL();
+   
+    gEpocEnv->iAppSrv = new (ELeave) CSdlAppServ();
+    gEpocEnv->iAppSrv->ConstructL();
+    
+    CSDL* sdl = new (ELeave) CSDL();
+    
+    gEpocEnv->iSdl = sdl;
+    
+    return sdl;
+    }
+    
+  /*  
+EXPORT_C void CSDL::ReInitL(TFlags aFlags)
+	{
+	const TFlags prevFlags = gEpocEnv->iEpocEnvFlags;
+	gEpocEnv->iEpocEnvFlags = aFlags;
+	TInt err = KErrNone;
+	if(((prevFlags & EDrawModeDSB) != (aFlags & EDrawModeDSB)) && gEpocEnv->iDsa)
+		{
+		delete gEpocEnv->iDsa;
+		gEpocEnv->iDsa = NULL;
+		gEpocEnv->iDsa = CDsa::RecreateL(EpocSdlEnv::Flags(CSDL::EDrawModeDSB));
+		}
+	}
+ */
+
+
+EXPORT_C void CSDL::SetContainerWindowL(RWindow& aWindow, RWsSession& aSession, CWsScreenDevice& aDevice)
+    {
+    if(gEpocEnv->iDsa == NULL)
+    	gEpocEnv->iDsa = CDsa::CreateL(aSession);
+    gEpocEnv->iDsa->ConstructL(aWindow, aDevice);
+    }
+        
+   
+EXPORT_C TThreadId CSDL::CallMainL(const TMainFunc& aFunc, TRequestStatus* const aStatus, const CDesC8Array* const aArg, TInt aFlags, TInt aStackSize)
+    {
+    ASSERT(gEpocEnv != NULL);
+    gEpocEnv->iMain = aFunc;
+    const TBool args = aArg != NULL;
+    
+    gEpocEnv->iArgc = aArg->Count() + 1;
+    gEpocEnv->iArgv = (char**) User::AllocL(sizeof(char*) * (gEpocEnv->iArgc + 1));  
+      
+    TInt k = 0;
+    const TFileName processName = RProcess().FileName();
+    const TInt len = processName.Length();
+    gEpocEnv->iArgv[k] = (char*) User::AllocL(len + 1);
+    Mem::Copy(gEpocEnv->iArgv[k], processName.Ptr(), len);
+    gEpocEnv->iArgv[k][len] = 0;
+      
+    for(TInt i =  0; args && (i < aArg->Count()); i++)
+        {
+        k++;
+        const TInt len = aArg->MdcaPoint(i).Length();
+        gEpocEnv->iArgv[k] = (char*) User::AllocL(len + 1);
+        Mem::Copy(gEpocEnv->iArgv[k], aArg->MdcaPoint(i).Ptr(), len);
+        gEpocEnv->iArgv[k][len] = 0;
+        }
+        
+    gEpocEnv->iArgv[gEpocEnv->iArgc] = NULL;
+         
+    RThread thread;
+    User::LeaveIfError(thread.Create(KSDLMain, DoMain, aStackSize, NULL, NULL));
+    
+    if(aStatus != NULL)
+    	{
+    	thread.Logon(*aStatus);
+    	}
+    	
+    gEpocEnv->iId = thread.Id();
+    thread.SetPriority(EPriorityLess);
+    if((aFlags & CSDL::ERequestResume) == 0)
+        {
+        thread.Resume();
+        }
+    thread.Close();
+    return gEpocEnv->iId;
+    }
+    
+EXPORT_C TInt CSDL::AppendWsEvent(const TWsEvent& aEvent)
+    {
+    return EpocSdlEnv::EventQueue().Append(aEvent);
+    }
+    
+EXPORT_C void CSDL::SDLPanic(const TDesC& aInfo, TInt aErr)
+    {
+    EpocSdlEnv::PanicMain(aInfo, aErr);
+    }
+    
+EXPORT_C TInt CSDL::GetSDLCode(TInt aScanCode)
+    {
+    if(aScanCode < 0)
+        return MAX_SCANCODE;
+    if(aScanCode >= MAX_SCANCODE)
+        return -1;
+    return KeyMap()[aScanCode];
+    }
+    
+EXPORT_C TInt CSDL::SDLCodesCount() const
+	{
+	return MAX_SCANCODE;
+	}
+	
+EXPORT_C void CSDL::ResetSDLCodes()
+	{
+	ResetKeyMap();
+	}
+    
+EXPORT_C void CSDL::SetOrientation(TOrientationMode aMode)
+	{
+	gEpocEnv->iDsa->SetOrientation(aMode);
+	}
+    
+EXPORT_C TInt CSDL::SetSDLCode(TInt aScanCode, TInt aSDLCode)
+    {
+    const TInt current = GetSDLCode(aScanCode);
+    if(aScanCode >= 0 && aScanCode < MAX_SCANCODE)
+        KeyMap()[aScanCode] = static_cast<SDLKey>(aSDLCode);
+    return current;
+    }
+
+
+EXPORT_C MSDLObserver* CSDL::Observer()
+	{
+	return gEpocEnv->iAppSrv->Observer();
+	}    
+    
+EXPORT_C void CSDL::SetObserver(MSDLObserver* aObserver)
+	{
+	gEpocEnv->iAppSrv->SetObserver(aObserver);
+	}
+	
+EXPORT_C void CSDL::Resume()
+	{
+	EpocSdlEnv::Resume();
+	}
+	
+EXPORT_C void CSDL::Suspend()
+	{
+	gEpocEnv->iDsa->DoStop();
+	}
+	
+EXPORT_C CSDL::CSDL()
+    {
+    }
+
+EXPORT_C void CSDL::DisableKeyBlocking(CAknAppUi& aAppUi) const
+	{
+	gEpocEnv->iAppUi = &aAppUi;
+	EnvUtils::DisableKeyBlocking();
+	}
+
+EXPORT_C TInt CSDL::SetBlitter(MBlitter* aBlitter)
+	{
+	if(gEpocEnv && gEpocEnv->iDsa)
+		{
+		gEpocEnv->iDsa->SetBlitter(aBlitter);
+		return KErrNone;
+		}
+	return KErrNotReady;
+	}
+		
+	
+EXPORT_C TInt CSDL::AppendOverlay(MOverlay& aOverlay, TInt aPriority)
+	{
+	if(gEpocEnv && gEpocEnv->iDsa)
+		{
+		return gEpocEnv->iDsa->AppendOverlay(aOverlay, aPriority);
+		}
+	return KErrNotReady;
+	}
+
+EXPORT_C TInt CSDL::RemoveOverlay(MOverlay& aOverlay)	
+	{
+	if(gEpocEnv && gEpocEnv->iDsa)
+		{
+		return gEpocEnv->iDsa->RemoveOverlay(aOverlay);
+		}
+	return KErrNotReady;
+	}
+
+EXPORT_C TInt CSDL::RedrawRequest()
+	{
+	if(gEpocEnv && gEpocEnv->iDsa)
+		{
+		return gEpocEnv->iDsa->RedrawRequest();
+		}
+	return KErrNotReady;
+	}
+	
+/*
+EXPORT_C CSDL* CSDL::Current()
+    {
+    return gEpocEnv != NULL ? gEpocEnv->iSdl : NULL;
+    }
+
+    
+EXPORT_C TInt CSDL::SetVolume(TInt aVolume)
+    {
+    return EpocSdlEnv::SetVolume(aVolume);
+    } 
+    
+EXPORT_C TInt CSDL::Volume() const
+    {
+    return EpocSdlEnv::Volume();
+    }     
+	
+EXPORT_C TInt CSDL::MaxVolume() const
+    {
+    return EpocSdlEnv::MaxVolume();
+    } 	
+*/
+			
+void EnvUtils::DisableKeyBlocking()
+	{
+	if(gEpocEnv->iAppUi != NULL)
+		return CCurrentAppUi::Cast(gEpocEnv->iAppUi)->DisableKeyBlocking();
+	}
+	
+TBool EnvUtils::Rendezvous(RThread& aThread, TRequestStatus& aStatus)
+	{
+	if(gEpocEnv->iId != TThreadId(0) &&
+    		 	aThread.Open(gEpocEnv->iId) &&
+    		  	aThread.ExitType() == EExitPending)
+    			{
+    			aThread.Rendezvous(aStatus);
+    			return ETrue;
+    			}
+    return EFalse;
+	}
+	
+	
+