Remove some panic crap.
[SDL.s60v3.git] / src / main / symbian / SDL_main.cpp
blob8f34d56e7bec4e5203ddc219c05725a82d52f64e
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 int iArgc;
34 char** iArgv;
35 CDsa* iDsa;
36 CSdlAppServ* iAppSrv;
37 TThreadId iId;
38 CArrayFix<TSdlCleanupItem>* iCleanupItems;
39 CSDL* iSdl;
40 TRequestStatus* iCallerStatus;
41 bool iWaitingForOrientationChange;
43 TSize iSize;
44 TDisplayMode iMode;
47 EpocSdlEnvData* gEpocEnv;
49 static void RunSingleThread()
51 int count = RThread().RequestCount();
52 if(count > 0)
54 int err;
55 if(CActiveScheduler::RunIfReady(err, CActive::EPriorityIdle))
57 CActiveScheduler::Current()->WaitForAnyRequest();
62 int Panic(int aErr, int aLine)
64 TBuf<64> b;
65 b.Format(_L("Main at %d"), aLine);
66 User::Panic(b, aErr);
67 return 0;
71 bool CEventQueue::HasData()
73 RunSingleThread();
74 return !m_queue.empty();
77 const TWsEvent CEventQueue::Shift()
79 const TWsEvent event = m_queue.front();
80 m_queue.pop();
81 return event;
85 TSdlCleanupItem::TSdlCleanupItem(TSdlCleanupOperation aOperation, void* aItem) :
86 iOperation(aOperation), iItem(aItem), iThread(RThread().Id())
89 #define MAINFUNC(x) TMainFunc::TMainFunc(mainfunc##x aFunc){Mem::FillZ(iMainFunc, sizeof(iMainFunc)); iMainFunc[x - 1] = (void*) aFunc;}
91 MAINFUNC(1)
92 MAINFUNC(2)
93 MAINFUNC(3)
94 MAINFUNC(4)
95 MAINFUNC(5)
96 MAINFUNC(6)
98 TMainFunc::TMainFunc()
100 Mem::FillZ(iMainFunc, sizeof(iMainFunc));
104 const void* TMainFunc::operator[](int aIndex) const
106 return iMainFunc[aIndex];
110 class CSdlAppServ : public CActive
112 public:
113 enum
115 EAppSrvNoop = CDsa::ELastDsaRequest,
116 EAppSrvWindowWidth,
117 EAppSrvWindowHeight,
118 EAppSrvWindowDisplayMode,
119 EAppSrvDsaStatus,
120 EAppSrvStopThread,
121 EAppSrvWaitDsa
123 CSdlAppServ();
124 void ConstructL();
125 ~CSdlAppServ();
126 int Request(int aService);
127 int RequestValue(int aService);
128 void Init();
129 void SetParam(int aParam);
131 private:
132 void RunL();
133 void DoCancel();
134 const TThreadId iMainId;
135 RThread iAppThread;
136 int iService;
137 int iReturnValue;
138 TRequestStatus* iStatusPtr;
141 CSdlAppServ::CSdlAppServ() : CActive(CActive::EPriorityHigh), iMainId(RThread().Id())
144 void CSdlAppServ::ConstructL()
146 CActiveScheduler::Add(this);
147 iStatus = KRequestPending;
148 iStatusPtr = &iStatus;
149 SetActive();
152 CSdlAppServ::~CSdlAppServ()
154 Cancel();
155 iAppThread.Close();
158 int CSdlAppServ::Request(int aService)
160 RunSingleThread();
161 iService = aService;
162 iAppThread.RequestComplete(iStatusPtr, KErrNone);
163 return KErrNone;
166 int CSdlAppServ::RequestValue(int aService)
168 Request(aService);
169 Request(EAppSrvNoop);
170 return iReturnValue;
173 void CSdlAppServ::Init()
175 PANIC_IF_ERROR(iAppThread.Open(iMainId));
178 void CSdlAppServ::SetParam(int aParam)
180 iReturnValue = aParam;
183 void CSdlAppServ::RunL()
185 if(iStatus == KErrNone)
187 switch(iService)
189 case CSdlAppServ::EAppSrvWaitDsa:
190 EpocSdlEnv::SetWaitDsa();
191 iReturnValue = EpocSdlEnv::IsDsaAvailable();
192 break;
194 case CSdlAppServ::EAppSrvStopThread:
195 if(gEpocEnv->iDsa != NULL)
196 gEpocEnv->iDsa->SetSuspend();
197 break;
199 case EAppSrvDsaStatus:
200 if(gEpocEnv->iDsa != NULL)
201 gEpocEnv->iDsa->Stop();
202 iReturnValue = KErrNone;
203 break;
205 case EAppSrvNoop:
206 break;
208 default:
209 PANIC(KErrNotSupported);
210 break;
213 iStatus = KRequestPending;
214 iStatusPtr = &iStatus;
215 SetActive();
219 void CSdlAppServ::DoCancel()
221 TRequestStatus* s = &iStatus;
222 iAppThread.RequestComplete(s, KErrCancel);
225 CEventQueue& EpocSdlEnv::EventQueue()
227 __ASSERT_DEBUG(gEpocEnv != NULL, PANIC(KErrNotReady));
228 return *gEpocEnv->iEventQueue;
231 int EpocSdlEnv::Argc()
233 __ASSERT_DEBUG(gEpocEnv != NULL, PANIC(KErrNotReady));
234 return gEpocEnv->iArgc;
237 char** EpocSdlEnv::Argv()
239 __ASSERT_DEBUG(gEpocEnv != NULL, PANIC(KErrNotReady));
240 return gEpocEnv->iArgv;
243 TBool EpocSdlEnv::IsDsaAvailable()
245 __ASSERT_DEBUG(gEpocEnv != NULL, PANIC(KErrNotReady));
246 return gEpocEnv->iDsa != NULL && gEpocEnv->iDsa->IsDsaAvailable();
249 void EpocSdlEnv::WaitDsaAvailable()
251 gEpocEnv->iAppSrv->Request(CSdlAppServ::EAppSrvStopThread);
254 int EpocSdlEnv::AllocSurface(const TSize& aSize, TDisplayMode aMode)
256 return gEpocEnv->iDsa->AllocSurface(aSize, aMode);
259 void EpocSdlEnv::UnlockHwSurface()
261 gEpocEnv->iDsa->UnlockHwSurface();
264 TUint8* EpocSdlEnv::LockHwSurface()
266 return gEpocEnv->iDsa->LockHwSurface();
269 void EpocSdlEnv::UpdateSwSurface()
271 gEpocEnv->iDsa->UpdateSwSurface();
274 TBool EpocSdlEnv::AddUpdateRect(TUint8* aAddress, const TRect& aUpdateRect, const TRect& aRect)
276 return gEpocEnv->iDsa->AddUpdateRect(aAddress, aUpdateRect, aRect);
279 void EpocSdlEnv::Request(int aService)
281 __ASSERT_DEBUG(gEpocEnv != NULL, PANIC(KErrNotReady));
282 gEpocEnv->iAppSrv->Request(aService);
285 TDisplayMode EpocSdlEnv::DisplayMode()
287 return gEpocEnv->iDsa == NULL ? ENone : gEpocEnv->iDsa->DisplayMode();
290 int EpocSdlEnv::SetPalette(int aFirstcolor, int aColorCount, TUint32* aPalette)
292 return gEpocEnv->iDsa->SetPalette(aFirstcolor, aColorCount, aPalette);
295 int EpocSdlEnv::AppendCleanupItem(const TSdlCleanupItem& aItem)
297 TRAPD(err, gEpocEnv->iCleanupItems->AppendL(aItem));
298 return err;
301 void EpocSdlEnv::RemoveCleanupItem(void* aItem)
303 for(int i = 0; i < gEpocEnv->iCleanupItems->Count(); i++)
305 if(gEpocEnv->iCleanupItems->At(i).iItem == aItem)
306 gEpocEnv->iCleanupItems->Delete(i);
310 void EpocSdlEnv::CleanupItems()
312 const TThreadId id = RThread().Id();
313 int last = gEpocEnv->iCleanupItems->Count() - 1;
314 int i;
316 for(i = last; i >= 0 ; i--)
318 TSdlCleanupItem& item = gEpocEnv->iCleanupItems->At(i);
319 if(item.iThread == id)
321 item.iThread = TThreadId(0);
322 item.iOperation(item.iItem);
326 last = gEpocEnv->iCleanupItems->Count() - 1;
328 for(i = last; i >= 0 ; i--)
330 TSdlCleanupItem& item = gEpocEnv->iCleanupItems->At(i);
331 if(item.iThread == TThreadId(0))
333 gEpocEnv->iCleanupItems->Delete(i);
338 void EpocSdlEnv::FreeSurface()
340 Request(CSdlAppServ::EAppSrvDsaStatus);
341 if(gEpocEnv->iDsa != NULL)
342 gEpocEnv->iDsa->Free();
345 //Dsa is a low priority ao, it has to wait if its pending event, but ws
346 //event has been prioritized before it
347 //this is not called from app thread!
348 void EpocSdlEnv::WaitDeviceChange()
350 gEpocEnv->iAppSrv->RequestValue(CSdlAppServ::EAppSrvWaitDsa);
353 static TBool CheckSdl()
355 int isExit = ETrue;
356 RThread sdl;
357 if(sdl.Open(gEpocEnv->iId) == KErrNone)
359 if(sdl.ExitType() == EExitPending)
361 isExit = EFalse;
363 sdl.Close();
365 return isExit;
368 void EpocSdlEnvData::Free()
370 if(RThread().Id() == gEpocEnv->iId)
372 if(iDsa != NULL)
373 iDsa->Free();
374 return;
377 __ASSERT_ALWAYS(iArgv == NULL || CheckSdl(), PANIC(KErrNotReady));
380 void EpocSdlEnvData::Delete()
382 for(int i = 0; i <= iArgc; i++)
384 if(iArgv != NULL)
385 delete[] iArgv[i];
388 delete[] iArgv;
390 iArgv = NULL;
391 iArgc = 0;
393 delete iEventQueue;
395 if(iDsa != NULL)
396 iDsa->Free();
398 delete iDsa;
399 delete iAppSrv;
402 static int MainL()
404 gEpocEnv->iCleanupItems = new CArrayFixFlat<TSdlCleanupItem>(8);
406 char** envp=0;
407 /* !! process exits here if there is "exit()" in main! */
408 int ret = 0;
409 for(int i = 0; i < 6; i++)
411 void* f = (void*) gEpocEnv->iMain[i];
412 if(f != NULL)
414 switch(i)
416 case 0:
417 ret = ((mainfunc1)f)();
418 return ret;
420 case 3:
421 ((mainfunc1)f)();
422 return ret;
424 case 1:
425 ret = ((mainfunc2)f)(EpocSdlEnv::Argc(), EpocSdlEnv::Argv());
426 return ret;
428 case 4:
429 ((mainfunc2)f)(EpocSdlEnv::Argc(), EpocSdlEnv::Argv());
430 return ret;
432 case 2:
433 ret = ((mainfunc3)f)(EpocSdlEnv::Argc(), EpocSdlEnv::Argv(), envp);
434 return ret;
436 case 5:
437 ((mainfunc3)f)(EpocSdlEnv::Argc(), EpocSdlEnv::Argv(), envp);
438 return ret;
442 PANIC(KErrNotFound);
443 return 0;
446 static int DoMain()
448 gEpocEnv->iAppSrv->Init();
450 TRAPD(err, err = MainL());
452 // Free resources and return
453 EpocSdlEnv::CleanupItems();
455 gEpocEnv->iCleanupItems->Reset();
456 delete gEpocEnv->iCleanupItems;
457 gEpocEnv->iCleanupItems = NULL;
459 gEpocEnv->Free(); //free up in thread resources
461 if(gEpocEnv->iCallerStatus != NULL)
463 User::RequestComplete(gEpocEnv->iCallerStatus, err);
464 return 0;
466 else
468 return err == KErrNone ? 0 : err;
472 CSDL::~CSDL()
474 gEpocEnv->Free();
475 gEpocEnv->Delete();
477 delete gEpocEnv;
478 gEpocEnv = NULL;
481 CSDL* CSDL::NewL()
483 __ASSERT_ALWAYS(gEpocEnv == NULL, PANIC(KErrAlreadyExists));
484 gEpocEnv = new EpocSdlEnvData;
485 Mem::FillZ(gEpocEnv, sizeof(EpocSdlEnvData));
487 gEpocEnv->iEventQueue = new CEventQueue();
488 gEpocEnv->iAppSrv = new CSdlAppServ();
490 CSDL* sdl = new CSDL();
492 gEpocEnv->iSdl = sdl;
494 return sdl;
497 void CSDL::SetContainerWindowL(RWindow& aWindow, RWsSession& aSession, CWsScreenDevice& aDevice)
499 if(gEpocEnv->iDsa == NULL)
500 gEpocEnv->iDsa = CDsa::CreateL(aSession);
501 gEpocEnv->iDsa->ConstructL(aWindow, aDevice);
504 int EpocSdlEnv::ApplyGlesDsa()
506 CDsa* dsa = NULL;
507 TRAPD(err, dsa = gEpocEnv->iDsa->CreateGlesDsaL());
508 gEpocEnv->iDsa = dsa;
509 return err;
512 RWindow* EpocSdlEnv::Window()
514 return gEpocEnv->iDsa->Window();
517 void EpocSdlEnv::UpdateWholeScreen(bool val)
519 gEpocEnv->iDsa->m_updateWholeScreen = val;
522 bool EpocSdlEnv::GetUpdateWholeScreen()
524 return gEpocEnv->iDsa->m_updateWholeScreen;
527 void EpocSdlEnv::SetOrientation(CAknAppUi::TAppUiOrientation orientation, const TSize& aSize, TDisplayMode aMode)
529 gEpocEnv->iWaitingForOrientationChange = true;
530 gEpocEnv->iSize = aSize;
531 gEpocEnv->iMode = aMode;
533 TRAPD(err, static_cast<CAknAppUi*>(CEikonEnv::Static()->EikAppUi())->SetOrientationL(orientation));
536 TThreadId CSDL::CallMainL(const TMainFunc& aFunc, TRequestStatus* const aStatus, const CDesC8Array* const aArg)
538 ASSERT(gEpocEnv != NULL);
539 gEpocEnv->iMain = aFunc;
540 const TBool args = aArg != NULL;
542 gEpocEnv->iArgc = args ? aArg->Count() + 1 : 0;
543 gEpocEnv->iArgv = new char*[gEpocEnv->iArgc + 2];
545 int k = 0;
546 const TFileName processName = RProcess().FileName();
547 const int len = processName.Length();
548 gEpocEnv->iArgv[k] = new char[len + 1];
549 memcpy(gEpocEnv->iArgv[k], processName.Ptr(), len);
550 gEpocEnv->iArgv[k][len] = 0;
552 for(int i = 0; args && (i < aArg->Count()); i++)
554 k++;
555 const int len = aArg->MdcaPoint(i).Length();
556 gEpocEnv->iArgv[k] = new char[len + 1];
557 memcpy(gEpocEnv->iArgv[k], aArg->MdcaPoint(i).Ptr(), len);
558 gEpocEnv->iArgv[k][len] = 0;
561 gEpocEnv->iArgv[k + 1] = NULL;
563 gEpocEnv->iAppSrv->ConstructL();
565 // for handling volume up/down keys
566 CRemConInterfaceSelector *iSelector = CRemConInterfaceSelector::NewL();
567 CRemConCoreApiTarget::NewL( *iSelector, *this );
568 iSelector->OpenTargetL();
570 gEpocEnv->iCallerStatus = aStatus;
571 if(aStatus != NULL)
572 *aStatus = KRequestPending;
573 gEpocEnv->iId = RThread().Id();
574 // when priority is not lowered screen updates much more frequently, which
575 // may be undesired, for example in case of openttd's generating world dialog
576 RThread().SetPriority(EPriorityLess);
577 DoMain();
579 return gEpocEnv->iId;
582 void CSDL::AppendWsEvent(const TWsEvent& aEvent)
584 EpocSdlEnv::EventQueue().Append(aEvent);
587 void CSDL::Resize()
589 if(gEpocEnv->iWaitingForOrientationChange)
591 EpocSdlEnv::AllocSurface(gEpocEnv->iSize, gEpocEnv->iMode);
592 gEpocEnv->iWaitingForOrientationChange = false;
594 else
596 TSize size = gEpocEnv->iDsa->Window()->Size();
597 SDL_PrivateResize(size.iWidth, size.iHeight);
601 void CSDL::MrccatoCommand(TRemConCoreApiOperationId aOperationId, TRemConCoreApiButtonAction aButtonAct)
603 if(aButtonAct != ERemConCoreApiButtonClick)
604 return;
606 TWsEvent event;
607 event.SetType(EEventKey);
608 event.SetTimeNow();
610 switch(aOperationId)
612 case ERemConCoreApiVolumeDown:
613 event.Key()->iScanCode = EStdKeyDecVolume;
614 event.SetType(EEventKeyDown);
615 AppendWsEvent(event);
616 event.SetType(EEventKeyUp);
617 AppendWsEvent(event);
618 break;
620 case ERemConCoreApiVolumeUp:
621 event.Key()->iScanCode = EStdKeyIncVolume;
622 event.SetType(EEventKeyDown);
623 AppendWsEvent(event);
624 event.SetType(EEventKeyUp);
625 AppendWsEvent(event);
626 break;
628 default:
629 break;