Remove thread id.
[SDL.s60v3.git] / src / main / symbian / SDL_main.cpp
blobe4c513b16b3448d00fb79b0de1b59fe6ba289467
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 CArrayFix<TSdlCleanupItem>* iCleanupItems;
35 CSDL* iSdl;
36 bool iWaitingForOrientationChange;
38 TSize iSize;
39 TDisplayMode iMode;
42 EpocSdlEnvData* gEpocEnv;
44 static void RunSingleThread()
46 if(RThread().RequestCount() > 0)
48 int err;
49 if(CActiveScheduler::RunIfReady(err, CActive::EPriorityIdle))
51 CActiveScheduler::Current()->WaitForAnyRequest();
56 int Panic(int aErr, int aLine)
58 TBuf<64> b;
59 b.Format(_L("Main at %d"), aLine);
60 User::Panic(b, aErr);
61 return 0;
65 bool CEventQueue::HasData()
67 RunSingleThread();
68 return !m_queue.empty();
71 const TWsEvent CEventQueue::Shift()
73 const TWsEvent event = m_queue.front();
74 m_queue.pop();
75 return event;
79 TSdlCleanupItem::TSdlCleanupItem(TSdlCleanupOperation aOperation, void* aItem) :
80 iOperation(aOperation), iItem(aItem), iThread(RThread().Id())
83 #define MAINFUNC(x) TMainFunc::TMainFunc(mainfunc##x aFunc){Mem::FillZ(iMainFunc, sizeof(iMainFunc)); iMainFunc[x - 1] = (void*) aFunc;}
85 MAINFUNC(1)
86 MAINFUNC(2)
87 MAINFUNC(3)
88 MAINFUNC(4)
89 MAINFUNC(5)
90 MAINFUNC(6)
92 TMainFunc::TMainFunc()
94 Mem::FillZ(iMainFunc, sizeof(iMainFunc));
97 const void* TMainFunc::operator[](int aIndex) const
99 return iMainFunc[aIndex];
102 class CSdlAppServ : public CActive
104 public:
105 enum
107 EAppSrvDsaStatus,
109 CSdlAppServ();
110 void ConstructL();
111 ~CSdlAppServ();
112 int Request(int aService);
113 void Init();
114 void SetParam(int aParam);
116 private:
117 void RunL();
118 void DoCancel();
119 const TThreadId iMainId;
120 RThread iAppThread;
121 int iService;
122 int iReturnValue;
123 TRequestStatus* iStatusPtr;
126 CSdlAppServ::CSdlAppServ() : CActive(CActive::EPriorityHigh), iMainId(RThread().Id())
129 void CSdlAppServ::ConstructL()
131 CActiveScheduler::Add(this);
132 iStatus = KRequestPending;
133 iStatusPtr = &iStatus;
134 SetActive();
137 CSdlAppServ::~CSdlAppServ()
139 Cancel();
140 iAppThread.Close();
143 int CSdlAppServ::Request(int aService)
145 RunSingleThread();
146 iService = aService;
147 iAppThread.RequestComplete(iStatusPtr, KErrNone);
148 return KErrNone;
151 void CSdlAppServ::Init()
153 PANIC_IF_ERROR(iAppThread.Open(iMainId));
156 void CSdlAppServ::SetParam(int aParam)
158 iReturnValue = aParam;
161 void CSdlAppServ::RunL()
163 if(iStatus == KErrNone)
165 switch(iService)
167 case EAppSrvDsaStatus:
168 if(gEpocEnv->iDsa != NULL)
169 gEpocEnv->iDsa->Stop();
170 iReturnValue = KErrNone;
171 break;
173 default:
174 PANIC(KErrNotSupported);
175 break;
178 iStatus = KRequestPending;
179 iStatusPtr = &iStatus;
180 SetActive();
184 void CSdlAppServ::DoCancel()
186 TRequestStatus* s = &iStatus;
187 iAppThread.RequestComplete(s, KErrCancel);
190 CEventQueue& EpocSdlEnv::EventQueue()
192 __ASSERT_DEBUG(gEpocEnv != NULL, PANIC(KErrNotReady));
193 return *gEpocEnv->iEventQueue;
196 TBool EpocSdlEnv::IsDsaAvailable()
198 __ASSERT_DEBUG(gEpocEnv != NULL, PANIC(KErrNotReady));
199 return gEpocEnv->iDsa != NULL && gEpocEnv->iDsa->IsDsaAvailable();
202 int EpocSdlEnv::AllocSurface(const TSize& aSize, TDisplayMode aMode)
204 return gEpocEnv->iDsa->AllocSurface(aSize, aMode);
207 void EpocSdlEnv::UnlockHwSurface()
209 gEpocEnv->iDsa->UnlockHwSurface();
212 TUint8* EpocSdlEnv::LockHwSurface()
214 return gEpocEnv->iDsa->LockHwSurface();
217 void EpocSdlEnv::UpdateSwSurface()
219 gEpocEnv->iDsa->UpdateSwSurface();
222 TBool EpocSdlEnv::AddUpdateRect(TUint8* aAddress, const TRect& aUpdateRect, const TRect& aRect)
224 return gEpocEnv->iDsa->AddUpdateRect(aAddress, aUpdateRect, aRect);
227 void EpocSdlEnv::Request(int aService)
229 __ASSERT_DEBUG(gEpocEnv != NULL, PANIC(KErrNotReady));
230 gEpocEnv->iAppSrv->Request(aService);
233 TDisplayMode EpocSdlEnv::DisplayMode()
235 return gEpocEnv->iDsa == NULL ? ENone : gEpocEnv->iDsa->DisplayMode();
238 int EpocSdlEnv::SetPalette(int aFirstcolor, int aColorCount, TUint32* aPalette)
240 return gEpocEnv->iDsa->SetPalette(aFirstcolor, aColorCount, aPalette);
243 int EpocSdlEnv::AppendCleanupItem(const TSdlCleanupItem& aItem)
245 TRAPD(err, gEpocEnv->iCleanupItems->AppendL(aItem));
246 return err;
249 void EpocSdlEnv::RemoveCleanupItem(void* aItem)
251 for(int i = 0; i < gEpocEnv->iCleanupItems->Count(); i++)
253 if(gEpocEnv->iCleanupItems->At(i).iItem == aItem)
254 gEpocEnv->iCleanupItems->Delete(i);
258 void EpocSdlEnv::CleanupItems()
260 const TThreadId id = RThread().Id();
261 int last = gEpocEnv->iCleanupItems->Count() - 1;
262 int i;
264 for(i = last; i >= 0 ; i--)
266 TSdlCleanupItem& item = gEpocEnv->iCleanupItems->At(i);
267 if(item.iThread == id)
269 item.iThread = TThreadId(0);
270 item.iOperation(item.iItem);
274 last = gEpocEnv->iCleanupItems->Count() - 1;
276 for(i = last; i >= 0 ; i--)
278 TSdlCleanupItem& item = gEpocEnv->iCleanupItems->At(i);
279 if(item.iThread == TThreadId(0))
281 gEpocEnv->iCleanupItems->Delete(i);
286 void EpocSdlEnv::FreeSurface()
288 Request(CSdlAppServ::EAppSrvDsaStatus);
289 if(gEpocEnv->iDsa != NULL)
290 gEpocEnv->iDsa->Free();
293 void EpocSdlEnvData::Free()
295 if(iDsa != NULL)
296 iDsa->Free();
299 void EpocSdlEnvData::Delete()
301 delete iEventQueue;
303 if(iDsa != NULL)
304 iDsa->Free();
306 delete iDsa;
307 delete iAppSrv;
310 static int MainL()
312 gEpocEnv->iCleanupItems = new CArrayFixFlat<TSdlCleanupItem>(8);
314 char** envp = 0;
315 char** argv = new char*[1];
316 argv[0] = new char[8];
317 strcpy(argv[0], "app.exe");
319 TMainFunc iMain = SDL_main;
321 /* !! process exits here if there is "exit()" in main! */
322 int ret = 0;
323 for(int i = 0; i < 6; i++)
325 void* f = (void*) iMain[i];
326 if(f != NULL)
328 switch(i)
330 case 0:
331 ret = ((mainfunc1)f)();
332 break;
334 case 3:
335 ((mainfunc1)f)();
336 break;
338 case 1:
339 ret = ((mainfunc2)f)(1, argv);
340 break;
342 case 4:
343 ((mainfunc2)f)(1, argv);
344 break;
346 case 2:
347 ret = ((mainfunc3)f)(1, argv, envp);
348 break;
350 case 5:
351 ((mainfunc3)f)(1, argv, envp);
352 break;
354 default:
355 break;
358 delete[] argv[0];
359 delete[] argv;
360 return ret;
364 PANIC(KErrNotFound);
365 return 0;
368 static int DoMain()
370 gEpocEnv->iAppSrv->Init();
372 TRAPD(err, err = MainL());
374 // Free resources and return
375 EpocSdlEnv::CleanupItems();
377 gEpocEnv->iCleanupItems->Reset();
378 delete gEpocEnv->iCleanupItems;
379 gEpocEnv->iCleanupItems = NULL;
381 gEpocEnv->Free(); //free up in thread resources
383 return err;
386 CSDL::CSDL()
388 __ASSERT_ALWAYS(gEpocEnv == NULL, PANIC(KErrAlreadyExists));
389 gEpocEnv = new EpocSdlEnvData;
390 Mem::FillZ(gEpocEnv, sizeof(EpocSdlEnvData));
392 gEpocEnv->iEventQueue = new CEventQueue();
393 gEpocEnv->iAppSrv = new CSdlAppServ();
395 gEpocEnv->iSdl = this;
398 CSDL::~CSDL()
400 gEpocEnv->Free();
401 gEpocEnv->Delete();
403 delete gEpocEnv;
404 gEpocEnv = NULL;
407 void CSDL::SetContainerWindowL(RWindow& aWindow, RWsSession& aSession, CWsScreenDevice& aDevice)
409 if(gEpocEnv->iDsa == NULL)
410 gEpocEnv->iDsa = CDsa::CreateL(aSession);
411 gEpocEnv->iDsa->ConstructL(aWindow, aDevice);
414 int EpocSdlEnv::ApplyGlesDsa()
416 CDsa* dsa = NULL;
417 TRAPD(err, dsa = gEpocEnv->iDsa->CreateGlesDsaL());
418 gEpocEnv->iDsa = dsa;
419 return err;
422 RWindow* EpocSdlEnv::Window()
424 return gEpocEnv->iDsa->Window();
427 void EpocSdlEnv::UpdateWholeScreen(bool val)
429 gEpocEnv->iDsa->m_updateWholeScreen = val;
432 bool EpocSdlEnv::GetUpdateWholeScreen()
434 return gEpocEnv->iDsa->m_updateWholeScreen;
437 void EpocSdlEnv::SetOrientation(CAknAppUi::TAppUiOrientation orientation, const TSize& aSize, TDisplayMode aMode)
439 gEpocEnv->iWaitingForOrientationChange = true;
440 gEpocEnv->iSize = aSize;
441 gEpocEnv->iMode = aMode;
443 TRAPD(err, static_cast<CAknAppUi*>(CEikonEnv::Static()->EikAppUi())->SetOrientationL(orientation));
446 void CSDL::CallMainL()
448 ASSERT(gEpocEnv != NULL);
450 gEpocEnv->iAppSrv->ConstructL();
452 // for handling volume up/down keys
453 CRemConInterfaceSelector *iSelector = CRemConInterfaceSelector::NewL();
454 CRemConCoreApiTarget::NewL( *iSelector, *this );
455 iSelector->OpenTargetL();
457 // when priority is not lowered screen updates much more frequently, which
458 // may be undesired, for example in case of openttd's generating world dialog
459 RThread().SetPriority(EPriorityLess);
460 DoMain();
463 void CSDL::AppendWsEvent(const TWsEvent& aEvent)
465 EpocSdlEnv::EventQueue().Append(aEvent);
468 void CSDL::Resize()
470 if(gEpocEnv->iWaitingForOrientationChange)
472 EpocSdlEnv::AllocSurface(gEpocEnv->iSize, gEpocEnv->iMode);
473 gEpocEnv->iWaitingForOrientationChange = false;
475 else
477 TSize size = gEpocEnv->iDsa->Window()->Size();
478 SDL_PrivateResize(size.iWidth, size.iHeight);
482 void CSDL::MrccatoCommand(TRemConCoreApiOperationId aOperationId, TRemConCoreApiButtonAction aButtonAct)
484 if(aButtonAct != ERemConCoreApiButtonClick)
485 return;
487 TWsEvent event;
488 event.SetType(EEventKey);
489 event.SetTimeNow();
491 switch(aOperationId)
493 case ERemConCoreApiVolumeDown:
494 event.Key()->iScanCode = EStdKeyDecVolume;
495 event.SetType(EEventKeyDown);
496 AppendWsEvent(event);
497 event.SetType(EEventKeyUp);
498 AppendWsEvent(event);
499 break;
501 case ERemConCoreApiVolumeUp:
502 event.Key()->iScanCode = EStdKeyIncVolume;
503 event.SetType(EEventKeyDown);
504 AppendWsEvent(event);
505 event.SetType(EEventKeyUp);
506 AppendWsEvent(event);
507 break;
509 default:
510 break;