Remove support for argv and argc.
[SDL.s60v3.git] / src / main / symbian / SDL_main.cpp
blobab20deadfd96a495d7f86b44a56669b9dfa94ea2
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 TMainFunc iMain;
33 CDsa* iDsa;
34 CSdlAppServ* iAppSrv;
35 TThreadId iId;
36 CArrayFix<TSdlCleanupItem>* iCleanupItems;
37 CSDL* iSdl;
38 TRequestStatus* iCallerStatus;
39 bool iWaitingForOrientationChange;
41 TSize iSize;
42 TDisplayMode iMode;
45 EpocSdlEnvData* gEpocEnv;
47 static void RunSingleThread()
49 if(RThread().RequestCount() > 0)
51 int err;
52 if(CActiveScheduler::RunIfReady(err, CActive::EPriorityIdle))
54 CActiveScheduler::Current()->WaitForAnyRequest();
59 int Panic(int aErr, int aLine)
61 TBuf<64> b;
62 b.Format(_L("Main at %d"), aLine);
63 User::Panic(b, aErr);
64 return 0;
68 bool CEventQueue::HasData()
70 RunSingleThread();
71 return !m_queue.empty();
74 const TWsEvent CEventQueue::Shift()
76 const TWsEvent event = m_queue.front();
77 m_queue.pop();
78 return event;
82 TSdlCleanupItem::TSdlCleanupItem(TSdlCleanupOperation aOperation, void* aItem) :
83 iOperation(aOperation), iItem(aItem), iThread(RThread().Id())
86 #define MAINFUNC(x) TMainFunc::TMainFunc(mainfunc##x aFunc){Mem::FillZ(iMainFunc, sizeof(iMainFunc)); iMainFunc[x - 1] = (void*) aFunc;}
88 MAINFUNC(1)
89 MAINFUNC(2)
90 MAINFUNC(3)
91 MAINFUNC(4)
92 MAINFUNC(5)
93 MAINFUNC(6)
95 TMainFunc::TMainFunc()
97 Mem::FillZ(iMainFunc, sizeof(iMainFunc));
101 const void* TMainFunc::operator[](int aIndex) const
103 return iMainFunc[aIndex];
106 class CSdlAppServ : public CActive
108 public:
109 enum
111 EAppSrvDsaStatus,
112 EAppSrvStopThread
114 CSdlAppServ();
115 void ConstructL();
116 ~CSdlAppServ();
117 int Request(int aService);
118 void Init();
119 void SetParam(int aParam);
121 private:
122 void RunL();
123 void DoCancel();
124 const TThreadId iMainId;
125 RThread iAppThread;
126 int iService;
127 int iReturnValue;
128 TRequestStatus* iStatusPtr;
131 CSdlAppServ::CSdlAppServ() : CActive(CActive::EPriorityHigh), iMainId(RThread().Id())
134 void CSdlAppServ::ConstructL()
136 CActiveScheduler::Add(this);
137 iStatus = KRequestPending;
138 iStatusPtr = &iStatus;
139 SetActive();
142 CSdlAppServ::~CSdlAppServ()
144 Cancel();
145 iAppThread.Close();
148 int CSdlAppServ::Request(int aService)
150 RunSingleThread();
151 iService = aService;
152 iAppThread.RequestComplete(iStatusPtr, KErrNone);
153 return KErrNone;
156 void CSdlAppServ::Init()
158 PANIC_IF_ERROR(iAppThread.Open(iMainId));
161 void CSdlAppServ::SetParam(int aParam)
163 iReturnValue = aParam;
166 void CSdlAppServ::RunL()
168 if(iStatus == KErrNone)
170 switch(iService)
172 case CSdlAppServ::EAppSrvStopThread:
173 if(gEpocEnv->iDsa != NULL)
174 gEpocEnv->iDsa->SetSuspend();
175 break;
177 case EAppSrvDsaStatus:
178 if(gEpocEnv->iDsa != NULL)
179 gEpocEnv->iDsa->Stop();
180 iReturnValue = KErrNone;
181 break;
183 default:
184 PANIC(KErrNotSupported);
185 break;
188 iStatus = KRequestPending;
189 iStatusPtr = &iStatus;
190 SetActive();
194 void CSdlAppServ::DoCancel()
196 TRequestStatus* s = &iStatus;
197 iAppThread.RequestComplete(s, KErrCancel);
200 CEventQueue& EpocSdlEnv::EventQueue()
202 __ASSERT_DEBUG(gEpocEnv != NULL, PANIC(KErrNotReady));
203 return *gEpocEnv->iEventQueue;
206 TBool EpocSdlEnv::IsDsaAvailable()
208 __ASSERT_DEBUG(gEpocEnv != NULL, PANIC(KErrNotReady));
209 return gEpocEnv->iDsa != NULL && gEpocEnv->iDsa->IsDsaAvailable();
212 void EpocSdlEnv::WaitDsaAvailable()
214 gEpocEnv->iAppSrv->Request(CSdlAppServ::EAppSrvStopThread);
217 int EpocSdlEnv::AllocSurface(const TSize& aSize, TDisplayMode aMode)
219 return gEpocEnv->iDsa->AllocSurface(aSize, aMode);
222 void EpocSdlEnv::UnlockHwSurface()
224 gEpocEnv->iDsa->UnlockHwSurface();
227 TUint8* EpocSdlEnv::LockHwSurface()
229 return gEpocEnv->iDsa->LockHwSurface();
232 void EpocSdlEnv::UpdateSwSurface()
234 gEpocEnv->iDsa->UpdateSwSurface();
237 TBool EpocSdlEnv::AddUpdateRect(TUint8* aAddress, const TRect& aUpdateRect, const TRect& aRect)
239 return gEpocEnv->iDsa->AddUpdateRect(aAddress, aUpdateRect, aRect);
242 void EpocSdlEnv::Request(int aService)
244 __ASSERT_DEBUG(gEpocEnv != NULL, PANIC(KErrNotReady));
245 gEpocEnv->iAppSrv->Request(aService);
248 TDisplayMode EpocSdlEnv::DisplayMode()
250 return gEpocEnv->iDsa == NULL ? ENone : gEpocEnv->iDsa->DisplayMode();
253 int EpocSdlEnv::SetPalette(int aFirstcolor, int aColorCount, TUint32* aPalette)
255 return gEpocEnv->iDsa->SetPalette(aFirstcolor, aColorCount, aPalette);
258 int EpocSdlEnv::AppendCleanupItem(const TSdlCleanupItem& aItem)
260 TRAPD(err, gEpocEnv->iCleanupItems->AppendL(aItem));
261 return err;
264 void EpocSdlEnv::RemoveCleanupItem(void* aItem)
266 for(int i = 0; i < gEpocEnv->iCleanupItems->Count(); i++)
268 if(gEpocEnv->iCleanupItems->At(i).iItem == aItem)
269 gEpocEnv->iCleanupItems->Delete(i);
273 void EpocSdlEnv::CleanupItems()
275 const TThreadId id = RThread().Id();
276 int last = gEpocEnv->iCleanupItems->Count() - 1;
277 int i;
279 for(i = last; i >= 0 ; i--)
281 TSdlCleanupItem& item = gEpocEnv->iCleanupItems->At(i);
282 if(item.iThread == id)
284 item.iThread = TThreadId(0);
285 item.iOperation(item.iItem);
289 last = gEpocEnv->iCleanupItems->Count() - 1;
291 for(i = last; i >= 0 ; i--)
293 TSdlCleanupItem& item = gEpocEnv->iCleanupItems->At(i);
294 if(item.iThread == TThreadId(0))
296 gEpocEnv->iCleanupItems->Delete(i);
301 void EpocSdlEnv::FreeSurface()
303 Request(CSdlAppServ::EAppSrvDsaStatus);
304 if(gEpocEnv->iDsa != NULL)
305 gEpocEnv->iDsa->Free();
308 static TBool CheckSdl()
310 int isExit = ETrue;
311 RThread sdl;
312 if(sdl.Open(gEpocEnv->iId) == KErrNone)
314 if(sdl.ExitType() == EExitPending)
316 isExit = EFalse;
318 sdl.Close();
320 return isExit;
323 void EpocSdlEnvData::Free()
325 if(RThread().Id() == gEpocEnv->iId)
327 if(iDsa != NULL)
328 iDsa->Free();
329 return;
332 __ASSERT_ALWAYS(CheckSdl(), PANIC(KErrNotReady));
335 void EpocSdlEnvData::Delete()
337 delete iEventQueue;
339 if(iDsa != NULL)
340 iDsa->Free();
342 delete iDsa;
343 delete iAppSrv;
346 static int MainL()
348 gEpocEnv->iCleanupItems = new CArrayFixFlat<TSdlCleanupItem>(8);
350 char** envp = 0;
351 char** argv = new char*[1];
352 argv[0] = new char[8];
353 strcpy(argv[0], "app.exe");
355 /* !! process exits here if there is "exit()" in main! */
356 int ret = 0;
357 for(int i = 0; i < 6; i++)
359 void* f = (void*) gEpocEnv->iMain[i];
360 if(f != NULL)
362 switch(i)
364 case 0:
365 ret = ((mainfunc1)f)();
366 break;
368 case 3:
369 ((mainfunc1)f)();
370 break;
372 case 1:
373 ret = ((mainfunc2)f)(1, argv);
374 break;
376 case 4:
377 ((mainfunc2)f)(1, argv);
378 break;
380 case 2:
381 ret = ((mainfunc3)f)(1, argv, envp);
382 break;
384 case 5:
385 ((mainfunc3)f)(1, argv, envp);
386 break;
388 default:
389 break;
392 delete[] argv[0];
393 delete[] argv;
394 return ret;
398 PANIC(KErrNotFound);
399 return 0;
402 static int DoMain()
404 gEpocEnv->iAppSrv->Init();
406 TRAPD(err, err = MainL());
408 // Free resources and return
409 EpocSdlEnv::CleanupItems();
411 gEpocEnv->iCleanupItems->Reset();
412 delete gEpocEnv->iCleanupItems;
413 gEpocEnv->iCleanupItems = NULL;
415 gEpocEnv->Free(); //free up in thread resources
417 if(gEpocEnv->iCallerStatus != NULL)
419 User::RequestComplete(gEpocEnv->iCallerStatus, err);
420 return 0;
422 else
424 return err == KErrNone ? 0 : err;
428 CSDL::~CSDL()
430 gEpocEnv->Free();
431 gEpocEnv->Delete();
433 delete gEpocEnv;
434 gEpocEnv = NULL;
437 CSDL* CSDL::NewL()
439 __ASSERT_ALWAYS(gEpocEnv == NULL, PANIC(KErrAlreadyExists));
440 gEpocEnv = new EpocSdlEnvData;
441 Mem::FillZ(gEpocEnv, sizeof(EpocSdlEnvData));
443 gEpocEnv->iEventQueue = new CEventQueue();
444 gEpocEnv->iAppSrv = new CSdlAppServ();
446 CSDL* sdl = new CSDL();
448 gEpocEnv->iSdl = sdl;
450 return sdl;
453 void CSDL::SetContainerWindowL(RWindow& aWindow, RWsSession& aSession, CWsScreenDevice& aDevice)
455 if(gEpocEnv->iDsa == NULL)
456 gEpocEnv->iDsa = CDsa::CreateL(aSession);
457 gEpocEnv->iDsa->ConstructL(aWindow, aDevice);
460 int EpocSdlEnv::ApplyGlesDsa()
462 CDsa* dsa = NULL;
463 TRAPD(err, dsa = gEpocEnv->iDsa->CreateGlesDsaL());
464 gEpocEnv->iDsa = dsa;
465 return err;
468 RWindow* EpocSdlEnv::Window()
470 return gEpocEnv->iDsa->Window();
473 void EpocSdlEnv::UpdateWholeScreen(bool val)
475 gEpocEnv->iDsa->m_updateWholeScreen = val;
478 bool EpocSdlEnv::GetUpdateWholeScreen()
480 return gEpocEnv->iDsa->m_updateWholeScreen;
483 void EpocSdlEnv::SetOrientation(CAknAppUi::TAppUiOrientation orientation, const TSize& aSize, TDisplayMode aMode)
485 gEpocEnv->iWaitingForOrientationChange = true;
486 gEpocEnv->iSize = aSize;
487 gEpocEnv->iMode = aMode;
489 TRAPD(err, static_cast<CAknAppUi*>(CEikonEnv::Static()->EikAppUi())->SetOrientationL(orientation));
492 TThreadId CSDL::CallMainL(const TMainFunc& aFunc, TRequestStatus* const aStatus)
494 ASSERT(gEpocEnv != NULL);
495 gEpocEnv->iMain = aFunc;
497 gEpocEnv->iAppSrv->ConstructL();
499 // for handling volume up/down keys
500 CRemConInterfaceSelector *iSelector = CRemConInterfaceSelector::NewL();
501 CRemConCoreApiTarget::NewL( *iSelector, *this );
502 iSelector->OpenTargetL();
504 gEpocEnv->iCallerStatus = aStatus;
505 if(aStatus != NULL)
506 *aStatus = KRequestPending;
507 gEpocEnv->iId = RThread().Id();
508 // when priority is not lowered screen updates much more frequently, which
509 // may be undesired, for example in case of openttd's generating world dialog
510 RThread().SetPriority(EPriorityLess);
511 DoMain();
513 return gEpocEnv->iId;
516 void CSDL::AppendWsEvent(const TWsEvent& aEvent)
518 EpocSdlEnv::EventQueue().Append(aEvent);
521 void CSDL::Resize()
523 if(gEpocEnv->iWaitingForOrientationChange)
525 EpocSdlEnv::AllocSurface(gEpocEnv->iSize, gEpocEnv->iMode);
526 gEpocEnv->iWaitingForOrientationChange = false;
528 else
530 TSize size = gEpocEnv->iDsa->Window()->Size();
531 SDL_PrivateResize(size.iWidth, size.iHeight);
535 void CSDL::MrccatoCommand(TRemConCoreApiOperationId aOperationId, TRemConCoreApiButtonAction aButtonAct)
537 if(aButtonAct != ERemConCoreApiButtonClick)
538 return;
540 TWsEvent event;
541 event.SetType(EEventKey);
542 event.SetTimeNow();
544 switch(aOperationId)
546 case ERemConCoreApiVolumeDown:
547 event.Key()->iScanCode = EStdKeyDecVolume;
548 event.SetType(EEventKeyDown);
549 AppendWsEvent(event);
550 event.SetType(EEventKeyUp);
551 AppendWsEvent(event);
552 break;
554 case ERemConCoreApiVolumeUp:
555 event.Key()->iScanCode = EStdKeyIncVolume;
556 event.SetType(EEventKeyDown);
557 AppendWsEvent(event);
558 event.SetType(EEventKeyUp);
559 AppendWsEvent(event);
560 break;
562 default:
563 break;