Remove symbianism.
[SDL.s60v3.git] / src / main / symbian / SDL_main.cpp
blob8e02606b6f31bd63a7fa41e764f95dc7b838558d
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 class CCurrentAppUi;
22 class CEikonEnv;
23 class CSdlAppServ;
24 class CEventQueue;
26 class EpocSdlEnvData
28 public:
29 void Free();
30 void Delete();
31 CEventQueue* iEventQueue;
32 CDsa* iDsa;
33 CSdlAppServ* iAppSrv;
34 TThreadId iId;
35 CArrayFix<TSdlCleanupItem>* iCleanupItems;
36 CSDL* iSdl;
37 bool iWaitingForOrientationChange;
39 TSize iSize;
40 TDisplayMode iMode;
43 EpocSdlEnvData* gEpocEnv;
45 static void RunSingleThread()
47 if(RThread().RequestCount() > 0)
49 int err;
50 if(CActiveScheduler::RunIfReady(err, CActive::EPriorityIdle))
52 CActiveScheduler::Current()->WaitForAnyRequest();
57 int Panic(int aErr, int aLine)
59 TBuf<64> b;
60 b.Format(_L("Main at %d"), aLine);
61 User::Panic(b, aErr);
62 return 0;
66 bool CEventQueue::HasData()
68 RunSingleThread();
69 return !m_queue.empty();
72 const TWsEvent CEventQueue::Shift()
74 const TWsEvent event = m_queue.front();
75 m_queue.pop();
76 return event;
80 TSdlCleanupItem::TSdlCleanupItem(TSdlCleanupOperation aOperation, void* aItem) :
81 iOperation(aOperation), iItem(aItem), iThread(RThread().Id())
84 #define MAINFUNC(x) TMainFunc::TMainFunc(mainfunc##x aFunc){Mem::FillZ(iMainFunc, sizeof(iMainFunc)); iMainFunc[x - 1] = (void*) aFunc;}
86 MAINFUNC(1)
87 MAINFUNC(2)
88 MAINFUNC(3)
89 MAINFUNC(4)
90 MAINFUNC(5)
91 MAINFUNC(6)
93 TMainFunc::TMainFunc()
95 Mem::FillZ(iMainFunc, sizeof(iMainFunc));
98 const void* TMainFunc::operator[](int aIndex) const
100 return iMainFunc[aIndex];
103 class CSdlAppServ : public CActive
105 public:
106 enum
108 EAppSrvDsaStatus,
109 EAppSrvStopThread
111 CSdlAppServ();
112 void ConstructL();
113 ~CSdlAppServ();
114 int Request(int aService);
115 void Init();
116 void SetParam(int aParam);
118 private:
119 void RunL();
120 void DoCancel();
121 const TThreadId iMainId;
122 RThread iAppThread;
123 int iService;
124 int iReturnValue;
125 TRequestStatus* iStatusPtr;
128 CSdlAppServ::CSdlAppServ() : CActive(CActive::EPriorityHigh), iMainId(RThread().Id())
131 void CSdlAppServ::ConstructL()
133 CActiveScheduler::Add(this);
134 iStatus = KRequestPending;
135 iStatusPtr = &iStatus;
136 SetActive();
139 CSdlAppServ::~CSdlAppServ()
141 Cancel();
142 iAppThread.Close();
145 int CSdlAppServ::Request(int aService)
147 RunSingleThread();
148 iService = aService;
149 iAppThread.RequestComplete(iStatusPtr, KErrNone);
150 return KErrNone;
153 void CSdlAppServ::Init()
155 PANIC_IF_ERROR(iAppThread.Open(iMainId));
158 void CSdlAppServ::SetParam(int aParam)
160 iReturnValue = aParam;
163 void CSdlAppServ::RunL()
165 if(iStatus == KErrNone)
167 switch(iService)
169 case CSdlAppServ::EAppSrvStopThread:
170 if(gEpocEnv->iDsa != NULL)
171 gEpocEnv->iDsa->SetSuspend();
172 break;
174 case EAppSrvDsaStatus:
175 if(gEpocEnv->iDsa != NULL)
176 gEpocEnv->iDsa->Stop();
177 iReturnValue = KErrNone;
178 break;
180 default:
181 PANIC(KErrNotSupported);
182 break;
185 iStatus = KRequestPending;
186 iStatusPtr = &iStatus;
187 SetActive();
191 void CSdlAppServ::DoCancel()
193 TRequestStatus* s = &iStatus;
194 iAppThread.RequestComplete(s, KErrCancel);
197 CEventQueue& EpocSdlEnv::EventQueue()
199 __ASSERT_DEBUG(gEpocEnv != NULL, PANIC(KErrNotReady));
200 return *gEpocEnv->iEventQueue;
203 TBool EpocSdlEnv::IsDsaAvailable()
205 __ASSERT_DEBUG(gEpocEnv != NULL, PANIC(KErrNotReady));
206 return gEpocEnv->iDsa != NULL && gEpocEnv->iDsa->IsDsaAvailable();
209 void EpocSdlEnv::WaitDsaAvailable()
211 gEpocEnv->iAppSrv->Request(CSdlAppServ::EAppSrvStopThread);
214 int EpocSdlEnv::AllocSurface(const TSize& aSize, TDisplayMode aMode)
216 return gEpocEnv->iDsa->AllocSurface(aSize, aMode);
219 void EpocSdlEnv::UnlockHwSurface()
221 gEpocEnv->iDsa->UnlockHwSurface();
224 TUint8* EpocSdlEnv::LockHwSurface()
226 return gEpocEnv->iDsa->LockHwSurface();
229 void EpocSdlEnv::UpdateSwSurface()
231 gEpocEnv->iDsa->UpdateSwSurface();
234 TBool EpocSdlEnv::AddUpdateRect(TUint8* aAddress, const TRect& aUpdateRect, const TRect& aRect)
236 return gEpocEnv->iDsa->AddUpdateRect(aAddress, aUpdateRect, aRect);
239 void EpocSdlEnv::Request(int aService)
241 __ASSERT_DEBUG(gEpocEnv != NULL, PANIC(KErrNotReady));
242 gEpocEnv->iAppSrv->Request(aService);
245 TDisplayMode EpocSdlEnv::DisplayMode()
247 return gEpocEnv->iDsa == NULL ? ENone : gEpocEnv->iDsa->DisplayMode();
250 int EpocSdlEnv::SetPalette(int aFirstcolor, int aColorCount, TUint32* aPalette)
252 return gEpocEnv->iDsa->SetPalette(aFirstcolor, aColorCount, aPalette);
255 int EpocSdlEnv::AppendCleanupItem(const TSdlCleanupItem& aItem)
257 TRAPD(err, gEpocEnv->iCleanupItems->AppendL(aItem));
258 return err;
261 void EpocSdlEnv::RemoveCleanupItem(void* aItem)
263 for(int i = 0; i < gEpocEnv->iCleanupItems->Count(); i++)
265 if(gEpocEnv->iCleanupItems->At(i).iItem == aItem)
266 gEpocEnv->iCleanupItems->Delete(i);
270 void EpocSdlEnv::CleanupItems()
272 const TThreadId id = RThread().Id();
273 int last = gEpocEnv->iCleanupItems->Count() - 1;
274 int i;
276 for(i = last; i >= 0 ; i--)
278 TSdlCleanupItem& item = gEpocEnv->iCleanupItems->At(i);
279 if(item.iThread == id)
281 item.iThread = TThreadId(0);
282 item.iOperation(item.iItem);
286 last = gEpocEnv->iCleanupItems->Count() - 1;
288 for(i = last; i >= 0 ; i--)
290 TSdlCleanupItem& item = gEpocEnv->iCleanupItems->At(i);
291 if(item.iThread == TThreadId(0))
293 gEpocEnv->iCleanupItems->Delete(i);
298 void EpocSdlEnv::FreeSurface()
300 Request(CSdlAppServ::EAppSrvDsaStatus);
301 if(gEpocEnv->iDsa != NULL)
302 gEpocEnv->iDsa->Free();
305 static TBool CheckSdl()
307 int isExit = ETrue;
308 RThread sdl;
309 if(sdl.Open(gEpocEnv->iId) == KErrNone)
311 if(sdl.ExitType() == EExitPending)
313 isExit = EFalse;
315 sdl.Close();
317 return isExit;
320 void EpocSdlEnvData::Free()
322 if(RThread().Id() == gEpocEnv->iId)
324 if(iDsa != NULL)
325 iDsa->Free();
326 return;
329 __ASSERT_ALWAYS(CheckSdl(), PANIC(KErrNotReady));
332 void EpocSdlEnvData::Delete()
334 delete iEventQueue;
336 if(iDsa != NULL)
337 iDsa->Free();
339 delete iDsa;
340 delete iAppSrv;
343 static int MainL()
345 gEpocEnv->iCleanupItems = new CArrayFixFlat<TSdlCleanupItem>(8);
347 char** envp = 0;
348 char** argv = new char*[1];
349 argv[0] = new char[8];
350 strcpy(argv[0], "app.exe");
352 TMainFunc iMain = SDL_main;
354 /* !! process exits here if there is "exit()" in main! */
355 int ret = 0;
356 for(int i = 0; i < 6; i++)
358 void* f = (void*) iMain[i];
359 if(f != NULL)
361 switch(i)
363 case 0:
364 ret = ((mainfunc1)f)();
365 break;
367 case 3:
368 ((mainfunc1)f)();
369 break;
371 case 1:
372 ret = ((mainfunc2)f)(1, argv);
373 break;
375 case 4:
376 ((mainfunc2)f)(1, argv);
377 break;
379 case 2:
380 ret = ((mainfunc3)f)(1, argv, envp);
381 break;
383 case 5:
384 ((mainfunc3)f)(1, argv, envp);
385 break;
387 default:
388 break;
391 delete[] argv[0];
392 delete[] argv;
393 return ret;
397 PANIC(KErrNotFound);
398 return 0;
401 static int DoMain()
403 gEpocEnv->iAppSrv->Init();
405 TRAPD(err, err = MainL());
407 // Free resources and return
408 EpocSdlEnv::CleanupItems();
410 gEpocEnv->iCleanupItems->Reset();
411 delete gEpocEnv->iCleanupItems;
412 gEpocEnv->iCleanupItems = NULL;
414 gEpocEnv->Free(); //free up in thread resources
416 return err;
419 CSDL::CSDL()
421 __ASSERT_ALWAYS(gEpocEnv == NULL, PANIC(KErrAlreadyExists));
422 gEpocEnv = new EpocSdlEnvData;
423 Mem::FillZ(gEpocEnv, sizeof(EpocSdlEnvData));
425 gEpocEnv->iEventQueue = new CEventQueue();
426 gEpocEnv->iAppSrv = new CSdlAppServ();
428 gEpocEnv->iSdl = this;
431 CSDL::~CSDL()
433 gEpocEnv->Free();
434 gEpocEnv->Delete();
436 delete gEpocEnv;
437 gEpocEnv = NULL;
440 void CSDL::SetContainerWindowL(RWindow& aWindow, RWsSession& aSession, CWsScreenDevice& aDevice)
442 if(gEpocEnv->iDsa == NULL)
443 gEpocEnv->iDsa = CDsa::CreateL(aSession);
444 gEpocEnv->iDsa->ConstructL(aWindow, aDevice);
447 int EpocSdlEnv::ApplyGlesDsa()
449 CDsa* dsa = NULL;
450 TRAPD(err, dsa = gEpocEnv->iDsa->CreateGlesDsaL());
451 gEpocEnv->iDsa = dsa;
452 return err;
455 RWindow* EpocSdlEnv::Window()
457 return gEpocEnv->iDsa->Window();
460 void EpocSdlEnv::UpdateWholeScreen(bool val)
462 gEpocEnv->iDsa->m_updateWholeScreen = val;
465 bool EpocSdlEnv::GetUpdateWholeScreen()
467 return gEpocEnv->iDsa->m_updateWholeScreen;
470 void EpocSdlEnv::SetOrientation(CAknAppUi::TAppUiOrientation orientation, const TSize& aSize, TDisplayMode aMode)
472 gEpocEnv->iWaitingForOrientationChange = true;
473 gEpocEnv->iSize = aSize;
474 gEpocEnv->iMode = aMode;
476 TRAPD(err, static_cast<CAknAppUi*>(CEikonEnv::Static()->EikAppUi())->SetOrientationL(orientation));
479 void CSDL::CallMainL()
481 ASSERT(gEpocEnv != NULL);
483 gEpocEnv->iAppSrv->ConstructL();
485 // for handling volume up/down keys
486 CRemConInterfaceSelector *iSelector = CRemConInterfaceSelector::NewL();
487 CRemConCoreApiTarget::NewL( *iSelector, *this );
488 iSelector->OpenTargetL();
490 gEpocEnv->iId = RThread().Id();
491 // when priority is not lowered screen updates much more frequently, which
492 // may be undesired, for example in case of openttd's generating world dialog
493 RThread().SetPriority(EPriorityLess);
494 DoMain();
497 void CSDL::AppendWsEvent(const TWsEvent& aEvent)
499 EpocSdlEnv::EventQueue().Append(aEvent);
502 void CSDL::Resize()
504 if(gEpocEnv->iWaitingForOrientationChange)
506 EpocSdlEnv::AllocSurface(gEpocEnv->iSize, gEpocEnv->iMode);
507 gEpocEnv->iWaitingForOrientationChange = false;
509 else
511 TSize size = gEpocEnv->iDsa->Window()->Size();
512 SDL_PrivateResize(size.iWidth, size.iHeight);
516 void CSDL::MrccatoCommand(TRemConCoreApiOperationId aOperationId, TRemConCoreApiButtonAction aButtonAct)
518 if(aButtonAct != ERemConCoreApiButtonClick)
519 return;
521 TWsEvent event;
522 event.SetType(EEventKey);
523 event.SetTimeNow();
525 switch(aOperationId)
527 case ERemConCoreApiVolumeDown:
528 event.Key()->iScanCode = EStdKeyDecVolume;
529 event.SetType(EEventKeyDown);
530 AppendWsEvent(event);
531 event.SetType(EEventKeyUp);
532 AppendWsEvent(event);
533 break;
535 case ERemConCoreApiVolumeUp:
536 event.Key()->iScanCode = EStdKeyIncVolume;
537 event.SetType(EEventKeyDown);
538 AppendWsEvent(event);
539 event.SetType(EEventKeyUp);
540 AppendWsEvent(event);
541 break;
543 default:
544 break;