Remove duplicated functions.
[SDL.s60v3.git] / src / main / symbian / SDL_main.cpp
blob03a1796cd7f2908871ab5bdf1c53c2e438fd1409
1 extern "C" {
2 #include "SDL_events_c.h"
4 #include "epoc_sdl.h"
5 #include "sdlepocapi.h"
6 #include <e32base.h>
7 #include <estlib.h>
8 #include <stdio.h>
9 #include <badesca.h>
10 #include <w32std.h>
11 #include <aknappui.h>
12 #include <aknapp.h>
13 #include "SDL_epocevents_c.h"
14 #include "SDL_keysym.h"
15 #include "dsa.h"
16 #include "SDL_loadso.h"
17 #include <remconcoreapitargetobserver.h>
18 #include <remconinterfaceselector.h>
19 #include <remconcoreapitarget.h>
21 extern SDLKey* KeyMap();
22 extern void ResetKeyMap();
24 class CCurrentAppUi;
25 class CEikonEnv;
26 class CSdlAppServ;
27 class CEventQueue;
29 class EpocSdlEnvData
31 public:
32 void Free();
33 void Delete();
34 CEventQueue* iEventQueue;
35 TMainFunc iMain;
36 int iArgc;
37 char** iArgv;
38 CDsa* iDsa;
39 CSdlAppServ* iAppSrv;
40 TThreadId iId;
41 CArrayFix<TSdlCleanupItem>* iCleanupItems;
42 CSDL* iSdl;
43 TRequestStatus* iCallerStatus;
44 bool iWaitingForOrientationChange;
46 TSize iSize;
47 TDisplayMode iMode;
50 EpocSdlEnvData* gEpocEnv;
52 static void RunSingleThread()
54 int count = RThread().RequestCount();
55 if(count > 0)
57 int err;
58 if(CActiveScheduler::RunIfReady(err, CActive::EPriorityIdle))
60 CActiveScheduler::Current()->WaitForAnyRequest();
65 int Panic(int aErr, int aLine)
67 TBuf<64> b;
68 b.Format(_L("Main at %d"), aLine);
69 User::Panic(b, aErr);
70 return 0;
74 bool CEventQueue::HasData()
76 RunSingleThread();
77 return !m_queue.empty();
80 const TWsEvent CEventQueue::Shift()
82 const TWsEvent event = m_queue.front();
83 m_queue.pop();
84 return event;
88 TSdlCleanupItem::TSdlCleanupItem(TSdlCleanupOperation aOperation, TAny* aItem) :
89 iOperation(aOperation), iItem(aItem), iThread(RThread().Id())
92 #define MAINFUNC(x) TMainFunc::TMainFunc(mainfunc##x aFunc){Mem::FillZ(iMainFunc, sizeof(iMainFunc)); iMainFunc[x - 1] = (void*) aFunc;}
94 MAINFUNC(1)
95 MAINFUNC(2)
96 MAINFUNC(3)
97 MAINFUNC(4)
98 MAINFUNC(5)
99 MAINFUNC(6)
101 TMainFunc::TMainFunc()
103 Mem::FillZ(iMainFunc, sizeof(iMainFunc));
107 const void* TMainFunc::operator[](int aIndex) const
109 return iMainFunc[aIndex];
113 class CSdlAppServ : public CActive
115 public:
116 enum
118 EAppSrvNoop = CDsa::ELastDsaRequest,
119 EAppSrvWindowWidth,
120 EAppSrvWindowHeight,
121 EAppSrvWindowDisplayMode,
122 EAppSrvWindowPointerCursorMode,
123 EAppSrvDsaStatus,
124 EAppSrvStopThread,
125 EAppSrvWaitDsa
127 CSdlAppServ();
128 void ConstructL();
129 ~CSdlAppServ();
130 int Request(int aService);
131 int RequestValue(int aService);
132 void Init();
133 void PanicMain(int aReason);
134 void PanicMain(const TDesC& aInfo, int aReason);
135 void SetParam(int aParam);
137 private:
138 void RunL();
139 void DoCancel();
140 const TThreadId iMainId;
141 RThread iAppThread;
142 int iService;
143 int iReturnValue;
144 TRequestStatus* iStatusPtr;
147 CSdlAppServ::CSdlAppServ() : CActive(CActive::EPriorityHigh), iMainId(RThread().Id())
150 void CSdlAppServ::PanicMain(int aReason)
152 iAppThread.Panic(RThread().Name(), aReason);
155 void CSdlAppServ::PanicMain(const TDesC& aInfo, int aReason)
157 iAppThread.Panic(aInfo, aReason);
160 void CSdlAppServ::ConstructL()
162 CActiveScheduler::Add(this);
163 iStatus = KRequestPending;
164 iStatusPtr = &iStatus;
165 SetActive();
168 CSdlAppServ::~CSdlAppServ()
170 Cancel();
171 iAppThread.Close();
174 int CSdlAppServ::Request(int aService)
176 RunSingleThread();
177 iService = aService;
178 iAppThread.RequestComplete(iStatusPtr, KErrNone);
179 return KErrNone;
182 int CSdlAppServ::RequestValue(int aService)
184 Request(aService);
185 Request(EAppSrvNoop);
186 return iReturnValue;
189 void CSdlAppServ::Init()
191 PANIC_IF_ERROR(iAppThread.Open(iMainId));
194 void CSdlAppServ::SetParam(int aParam)
196 iReturnValue = aParam;
199 void CSdlAppServ::RunL()
201 if(iStatus == KErrNone)
203 switch(iService)
205 case CSdlAppServ::EAppSrvWaitDsa:
206 EpocSdlEnv::SetWaitDsa();
207 iReturnValue = EpocSdlEnv::IsDsaAvailable();
208 break;
210 case CSdlAppServ::EAppSrvStopThread:
211 if(gEpocEnv->iDsa != NULL)
212 gEpocEnv->iDsa->SetSuspend();
213 break;
215 case EAppSrvWindowPointerCursorMode:
216 iReturnValue = gEpocEnv->iDsa != NULL ? gEpocEnv->iDsa->Session().PointerCursorMode() : KErrNotReady;
217 break;
219 case EAppSrvDsaStatus:
220 if(gEpocEnv->iDsa != NULL)
221 gEpocEnv->iDsa->Stop();
222 iReturnValue = KErrNone;
223 break;
225 case EAppSrvNoop:
226 break;
228 default:
229 PANIC(KErrNotSupported);
230 break;
233 iStatus = KRequestPending;
234 iStatusPtr = &iStatus;
235 SetActive();
239 void CSdlAppServ::DoCancel()
241 TRequestStatus* s = &iStatus;
242 iAppThread.RequestComplete(s, KErrCancel);
245 CEventQueue& EpocSdlEnv::EventQueue()
247 __ASSERT_DEBUG(gEpocEnv != NULL, PANIC(KErrNotReady));
248 return *gEpocEnv->iEventQueue;
251 int EpocSdlEnv::Argc()
253 __ASSERT_DEBUG(gEpocEnv != NULL, PANIC(KErrNotReady));
254 return gEpocEnv->iArgc;
257 char** EpocSdlEnv::Argv()
259 __ASSERT_DEBUG(gEpocEnv != NULL, PANIC(KErrNotReady));
260 return gEpocEnv->iArgv;
263 TBool EpocSdlEnv::IsDsaAvailable()
265 __ASSERT_DEBUG(gEpocEnv != NULL, PANIC(KErrNotReady));
266 return gEpocEnv->iDsa != NULL && gEpocEnv->iDsa->IsDsaAvailable();
269 void EpocSdlEnv::WaitDsaAvailable()
271 gEpocEnv->iAppSrv->Request(CSdlAppServ::EAppSrvStopThread);
274 void EpocSdlEnv::Suspend()
276 if(gEpocEnv->iDsa != NULL)
278 gEpocEnv->iDsa->SetSuspend();
282 void EpocSdlEnv::SetWaitDsa()
284 if(!IsDsaAvailable())
286 if(gEpocEnv->iDsa != NULL)
287 gEpocEnv->iDsa->SetSuspend();
291 void EpocSdlEnv::Resume()
293 if(gEpocEnv->iDsa != NULL)
295 gEpocEnv->iDsa->Resume();
299 int EpocSdlEnv::AllocSurface(const TSize& aSize, TDisplayMode aMode)
301 return gEpocEnv->iDsa->AllocSurface(aSize, aMode);
304 void EpocSdlEnv::UnlockHwSurface()
306 gEpocEnv->iDsa->UnlockHwSurface();
309 TUint8* EpocSdlEnv::LockHwSurface()
311 return gEpocEnv->iDsa->LockHwSurface();
314 void EpocSdlEnv::UpdateSwSurface()
316 gEpocEnv->iDsa->UpdateSwSurface();
319 TBool EpocSdlEnv::AddUpdateRect(TUint8* aAddress, const TRect& aUpdateRect, const TRect& aRect)
321 return gEpocEnv->iDsa->AddUpdateRect(aAddress, aUpdateRect, aRect);
324 void EpocSdlEnv::Request(int aService)
326 __ASSERT_DEBUG(gEpocEnv != NULL, PANIC(KErrNotReady));
327 gEpocEnv->iAppSrv->Request(aService);
330 TDisplayMode EpocSdlEnv::DisplayMode()
332 return gEpocEnv->iDsa == NULL ? ENone : gEpocEnv->iDsa->DisplayMode();
335 TPointerCursorMode EpocSdlEnv::PointerMode()
337 return static_cast<TPointerCursorMode>(gEpocEnv->iAppSrv->RequestValue(CSdlAppServ::EAppSrvWindowPointerCursorMode));
340 int EpocSdlEnv::SetPalette(int aFirstcolor, int aColorCount, TUint32* aPalette)
342 return gEpocEnv->iDsa->SetPalette(aFirstcolor, aColorCount, aPalette);
345 void EpocSdlEnv::PanicMain(int aErr)
347 gEpocEnv->iAppSrv->PanicMain(aErr);
351 int EpocSdlEnv::AppendCleanupItem(const TSdlCleanupItem& aItem)
353 TRAPD(err, gEpocEnv->iCleanupItems->AppendL(aItem));
354 return err;
357 void EpocSdlEnv::RemoveCleanupItem(TAny* aItem)
359 for(int i = 0; i < gEpocEnv->iCleanupItems->Count(); i++)
361 if(gEpocEnv->iCleanupItems->At(i).iItem == aItem)
362 gEpocEnv->iCleanupItems->Delete(i);
366 void EpocSdlEnv::CleanupItems()
368 const TThreadId id = RThread().Id();
369 int last = gEpocEnv->iCleanupItems->Count() - 1;
370 int i;
372 for(i = last; i >= 0 ; i--)
374 TSdlCleanupItem& item = gEpocEnv->iCleanupItems->At(i);
375 if(item.iThread == id)
377 item.iThread = TThreadId(0);
378 item.iOperation(item.iItem);
382 last = gEpocEnv->iCleanupItems->Count() - 1;
384 for(i = last; i >= 0 ; i--)
386 TSdlCleanupItem& item = gEpocEnv->iCleanupItems->At(i);
387 if(item.iThread == TThreadId(0))
389 gEpocEnv->iCleanupItems->Delete(i);
394 void EpocSdlEnv::FreeSurface()
396 Request(CSdlAppServ::EAppSrvDsaStatus);
397 if(gEpocEnv->iDsa != NULL)
398 gEpocEnv->iDsa->Free();
401 void EpocSdlEnv::PanicMain(const TDesC& aInfo, int aErr)
403 gEpocEnv->iAppSrv->PanicMain(aInfo, aErr);
406 //Dsa is a low priority ao, it has to wait if its pending event, but ws
407 //event has been prioritized before it
408 //this is not called from app thread!
409 void EpocSdlEnv::WaitDeviceChange()
411 gEpocEnv->iAppSrv->RequestValue(CSdlAppServ::EAppSrvWaitDsa);
414 static TBool CheckSdl()
416 int isExit = ETrue;
417 RThread sdl;
418 if(sdl.Open(gEpocEnv->iId) == KErrNone)
420 if(sdl.ExitType() == EExitPending)
422 isExit = EFalse;
424 sdl.Close();
426 return isExit;
429 void EpocSdlEnvData::Free()
431 if(RThread().Id() == gEpocEnv->iId)
433 if(iDsa != NULL)
434 iDsa->Free();
435 return;
438 __ASSERT_ALWAYS(iArgv == NULL || CheckSdl(), PANIC(KErrNotReady));
441 void EpocSdlEnvData::Delete()
443 for(int i = 0; i <= iArgc; i++)
445 if(iArgv != NULL)
446 delete[] iArgv[i];
449 delete[] iArgv;
451 iArgv = NULL;
452 iArgc = 0;
454 delete iEventQueue;
456 if(iDsa != NULL)
457 iDsa->Free();
459 delete iDsa;
460 delete iAppSrv;
463 static int MainL()
465 gEpocEnv->iCleanupItems = new CArrayFixFlat<TSdlCleanupItem>(8);
467 char** envp=0;
468 /* !! process exits here if there is "exit()" in main! */
469 int ret = 0;
470 for(int i = 0; i < 6; i++)
472 void* f = (void*) gEpocEnv->iMain[i];
473 if(f != NULL)
475 switch(i)
477 case 0:
478 ret = ((mainfunc1)f)();
479 return ret;
481 case 3:
482 ((mainfunc1)f)();
483 return ret;
485 case 1:
486 ret = ((mainfunc2)f)(EpocSdlEnv::Argc(), EpocSdlEnv::Argv());
487 return ret;
489 case 4:
490 ((mainfunc2)f)(EpocSdlEnv::Argc(), EpocSdlEnv::Argv());
491 return ret;
493 case 2:
494 ret = ((mainfunc3)f)(EpocSdlEnv::Argc(), EpocSdlEnv::Argv(), envp);
495 return ret;
497 case 5:
498 ((mainfunc3)f)(EpocSdlEnv::Argc(), EpocSdlEnv::Argv(), envp);
499 return ret;
503 PANIC(KErrNotFound);
504 return 0;
507 static int DoMain()
509 TBool fbsconnected = EFalse;
511 gEpocEnv->iAppSrv->Init();
513 TRAPD(err, err = MainL());
515 // Free resources and return
516 EpocSdlEnv::CleanupItems();
518 gEpocEnv->iCleanupItems->Reset();
519 delete gEpocEnv->iCleanupItems;
520 gEpocEnv->iCleanupItems = NULL;
522 gEpocEnv->Free(); //free up in thread resources
524 if(fbsconnected)
525 RFbsSession::Disconnect();
527 if(gEpocEnv->iCallerStatus != NULL)
529 User::RequestComplete(gEpocEnv->iCallerStatus, err);
530 return 0;
532 else
534 return err == KErrNone ? 0 : err;
538 CSDL::~CSDL()
540 gEpocEnv->Free();
541 gEpocEnv->Delete();
543 delete gEpocEnv;
544 gEpocEnv = NULL;
547 CSDL* CSDL::NewL()
549 __ASSERT_ALWAYS(gEpocEnv == NULL, PANIC(KErrAlreadyExists));
550 gEpocEnv = new EpocSdlEnvData;
551 Mem::FillZ(gEpocEnv, sizeof(EpocSdlEnvData));
553 gEpocEnv->iEventQueue = new CEventQueue();
554 gEpocEnv->iAppSrv = new CSdlAppServ();
556 CSDL* sdl = new CSDL();
558 gEpocEnv->iSdl = sdl;
560 return sdl;
563 void CSDL::SetContainerWindowL(RWindow& aWindow, RWsSession& aSession, CWsScreenDevice& aDevice)
565 if(gEpocEnv->iDsa == NULL)
566 gEpocEnv->iDsa = CDsa::CreateL(aSession);
567 gEpocEnv->iDsa->ConstructL(aWindow, aDevice);
570 int EpocSdlEnv::ApplyGlesDsa()
572 CDsa* dsa = NULL;
573 TRAPD(err, dsa = gEpocEnv->iDsa->CreateGlesDsaL());
574 gEpocEnv->iDsa = dsa;
575 return err;
578 RWindow* EpocSdlEnv::Window()
580 return gEpocEnv->iDsa->Window();
583 void EpocSdlEnv::UpdateWholeScreen(bool val)
585 gEpocEnv->iDsa->m_updateWholeScreen = val;
588 bool EpocSdlEnv::GetUpdateWholeScreen()
590 return gEpocEnv->iDsa->m_updateWholeScreen;
593 void EpocSdlEnv::SetOrientation(CAknAppUi::TAppUiOrientation orientation, const TSize& aSize, TDisplayMode aMode)
595 gEpocEnv->iWaitingForOrientationChange = true;
596 gEpocEnv->iSize = aSize;
597 gEpocEnv->iMode = aMode;
599 TRAPD(err, static_cast<CAknAppUi*>(CEikonEnv::Static()->EikAppUi())->SetOrientationL(orientation));
602 TThreadId CSDL::CallMainL(const TMainFunc& aFunc, TRequestStatus* const aStatus, const CDesC8Array* const aArg)
604 ASSERT(gEpocEnv != NULL);
605 gEpocEnv->iMain = aFunc;
606 const TBool args = aArg != NULL;
608 gEpocEnv->iArgc = args ? aArg->Count() + 1 : 0;
609 gEpocEnv->iArgv = new char*[gEpocEnv->iArgc + 2];
611 int k = 0;
612 const TFileName processName = RProcess().FileName();
613 const int len = processName.Length();
614 gEpocEnv->iArgv[k] = new char[len + 1];
615 Mem::Copy(gEpocEnv->iArgv[k], processName.Ptr(), len);
616 gEpocEnv->iArgv[k][len] = 0;
618 for(int i = 0; args && (i < aArg->Count()); i++)
620 k++;
621 const int len = aArg->MdcaPoint(i).Length();
622 gEpocEnv->iArgv[k] = new char[len + 1];
623 Mem::Copy(gEpocEnv->iArgv[k], aArg->MdcaPoint(i).Ptr(), len);
624 gEpocEnv->iArgv[k][len] = 0;
627 gEpocEnv->iArgv[k + 1] = NULL;
629 gEpocEnv->iAppSrv->ConstructL();
631 // for handling volume up/down keys
632 CRemConInterfaceSelector *iSelector = CRemConInterfaceSelector::NewL();
633 CRemConCoreApiTarget::NewL( *iSelector, *this );
634 iSelector->OpenTargetL();
636 gEpocEnv->iCallerStatus = aStatus;
637 if(aStatus != NULL)
638 *aStatus = KRequestPending;
639 gEpocEnv->iId = RThread().Id();
640 // when priority is not lowered screen updates much more frequently, which
641 // may be undesired, for example in case of openttd's generating world dialog
642 RThread().SetPriority(EPriorityLess);
643 DoMain();
645 return gEpocEnv->iId;
648 void CSDL::AppendWsEvent(const TWsEvent& aEvent)
650 EpocSdlEnv::EventQueue().Append(aEvent);
653 void CSDL::SDLPanic(const TDesC& aInfo, int aErr)
655 EpocSdlEnv::PanicMain(aInfo, aErr);
658 int CSDL::GetSDLCode(int aScanCode)
660 if(aScanCode < 0)
661 return MAX_SCANCODE;
662 if(aScanCode >= MAX_SCANCODE)
663 return -1;
664 return KeyMap()[aScanCode];
667 int CSDL::SDLCodesCount() const
669 return MAX_SCANCODE;
672 void CSDL::ResetSDLCodes()
674 ResetKeyMap();
677 int CSDL::SetSDLCode(int aScanCode, int aSDLCode)
679 const int current = GetSDLCode(aScanCode);
680 if(aScanCode >= 0 && aScanCode < MAX_SCANCODE)
681 KeyMap()[aScanCode] = static_cast<SDLKey>(aSDLCode);
682 return current;
685 void CSDL::Resume()
687 EpocSdlEnv::Resume();
690 void CSDL::Suspend()
692 if(gEpocEnv->iDsa != NULL)
693 gEpocEnv->iDsa->DoStop();
696 void CSDL::Resize()
698 if(gEpocEnv->iWaitingForOrientationChange)
700 EpocSdlEnv::AllocSurface(gEpocEnv->iSize, gEpocEnv->iMode);
701 gEpocEnv->iWaitingForOrientationChange = false;
703 else
705 TSize size = gEpocEnv->iDsa->Window()->Size();
706 SDL_PrivateResize(size.iWidth, size.iHeight);
710 void CSDL::MrccatoCommand(TRemConCoreApiOperationId aOperationId, TRemConCoreApiButtonAction aButtonAct)
712 if(aButtonAct != ERemConCoreApiButtonClick)
713 return;
715 TWsEvent event;
716 event.SetType(EEventKey);
717 event.SetTimeNow();
719 switch(aOperationId)
721 case ERemConCoreApiVolumeDown:
722 event.Key()->iScanCode = EStdKeyDecVolume;
723 event.SetType(EEventKeyDown);
724 AppendWsEvent(event);
725 event.SetType(EEventKeyUp);
726 AppendWsEvent(event);
727 break;
729 case ERemConCoreApiVolumeUp:
730 event.Key()->iScanCode = EStdKeyIncVolume;
731 event.SetType(EEventKeyDown);
732 AppendWsEvent(event);
733 event.SetType(EEventKeyUp);
734 AppendWsEvent(event);
735 break;
737 default:
738 break;