]> git.vomp.tv Git - vompclient.git/blob - winmain.cc
Windows port
[vompclient.git] / winmain.cc
1 /*\r
2     Copyright 2004-2005 Chris Tallon\r
3 \r
4     This file is part of VOMP.\r
5 \r
6     VOMP is free software; you can redistribute it and/or modify\r
7     it under the terms of the GNU General Public License as published by\r
8     the Free Software Foundation; either version 2 of the License, or\r
9     (at your option) any later version.\r
10 \r
11     VOMP is distributed in the hope that it will be useful,\r
12     but WITHOUT ANY WARRANTY; without even the implied warranty of\r
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
14     GNU General Public License for more details.\r
15 \r
16     You should have received a copy of the GNU General Public License\r
17     along with VOMP; if not, write to the Free Software\r
18     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\r
19 */\r
20 #ifdef WIN32\r
21 #include <stdio.h>\r
22 #include <stdlib.h>\r
23 #include <string.h>\r
24 #include <signal.h>\r
25 \r
26 #define _WIN32_WINNT 0x501\r
27 #include <winsock2.h>\r
28 #include <windows.h>\r
29 \r
30 #include "vompreswin.h"\r
31 \r
32 #include "defines.h"\r
33 #include "log.h"\r
34 #include "remotewin.h"\r
35 #include "ledwin.h"\r
36 #include "mtdwin.h"\r
37 #include "timers.h"\r
38 #include "videowin.h"\r
39 #include "audiowin.h"\r
40 #include "vdr.h"\r
41 #include "osdwin.h"\r
42 #include "viewman.h"\r
43 #include "command.h"\r
44 \r
45 void sighandler(int signalReceived);\r
46 void shutdown(int code);\r
47 \r
48 // Global variables --------------------------------------------------------------------------------------------------\r
49 int debugEnabled = 0;\r
50 Log* logger;\r
51 Remote* remote;\r
52 Mtd* mtd;\r
53 Led* led;\r
54 Osd* osd;\r
55 Timers* timers;\r
56 ViewMan* viewman;\r
57 Command* command;\r
58 VDR* vdr;\r
59 Video* video;\r
60 Audio* audio;\r
61 bool wnd_fullscreen=false;\r
62 RECT wnd_fs_rect={20,20,768+20,576+20};\r
63 RECT wnd_fs_rect_client={0,0,768,576};\r
64 \r
65 \r
66 void MILLISLEEP(ULONG a)
67 {
68
69   Sleep(a);
70
71 }\r
72 \r
73 DWORD WINAPI commandthreadStart(void *arg)\r
74 {\r
75          command->run();\r
76          return 0;\r
77 }\r
78 \r
79 bool InitApp(HINSTANCE hinst,int cmdshow);\r
80 \r
81 HWND win_main;//global window handle\r
82 HWND win;//global child window handle\r
83 HACCEL acc;\r
84 \r
85 #define ERROR_MSG(str) MessageBox(win_main,str,"Error!",MB_OK|MB_ICONWARNING)\r
86 INT WINAPI WinMain( HINSTANCE hinst , HINSTANCE previnst, LPSTR cmdline, int cmdshow)\r
87 {\r
88   //On Windows we have to init a window, we use DXUT\r
89         if (!InitApp(hinst,cmdshow)) return false;\r
90   //Starting Network support\r
91   WSADATA wsadat; \r
92   int result = WSAStartup(MAKEWORD(2,2),&wsadat);\r
93   if (result!=NO_ERROR) {\r
94         ERROR_MSG("Initialising WinSocked: Error at WSAStartup()\n");\r
95                 return 0;\r
96   }\r
97   result= CoInitializeEx(NULL,COINIT_MULTITHREADED );//Initialize COM for DirectShow\r
98   if (result!=S_OK) {\r
99           ERROR_MSG("Initialising COM: Error at Coinitialize()\n");\r
100           return 0;\r
101   }\r
102 \r
103 \r
104 \r
105 \r
106   // Init global vars ------------------------------------------------------------------------------------------------\r
107 \r
108   logger     = new Log();\r
109   remote     = new RemoteWin();\r
110   mtd        = new MtdWin();\r
111   led        = new LedWin();\r
112   timers     = new Timers();\r
113   osd        = new OsdWin();\r
114   vdr        = new VDR();\r
115   video      = new VideoWin();\r
116   audio      = new AudioWin();\r
117   viewman    = new ViewMan();\r
118   command    = new Command();\r
119 \r
120   if (!logger || !remote || !mtd || !led || !osd || !video || !audio || !viewman || !command)\r
121   {\r
122     ERROR_MSG("Could not create objects. Memory problems?\n");\r
123     shutdown(1);\r
124         WSACleanup();\r
125         return 0;\r
126   }\r
127 \r
128   // Get logging module started --------------------------------------------------------------------------------------\r
129 \r
130   if (!logger->init(Log::DEBUG, "vompwin.log", true))\r
131   {\r
132     ERROR_MSG("Could not initialise log object. Aborting.\n");\r
133     shutdown(1);\r
134         WSACleanup();\r
135         return 0;\r
136   }\r
137 \r
138   logger->log("Core", Log::INFO, "Starting up...");\r
139   \r
140 \r
141 \r
142   // Init modules ----------------------------------------------------------------------------------------------------\r
143   int success;\r
144 \r
145   success = remote->init("/dev/rawir");\r
146   if (success)\r
147   {\r
148     logger->log("Core", Log::INFO, "Remote module initialised");\r
149   }\r
150   else\r
151   {\r
152     logger->log("Core", Log::EMERG, "Remote module failed to initialise");\r
153     shutdown(1);\r
154         WSACleanup();\r
155         return 0;\r
156   }\r
157 \r
158   success = led->init(0);\r
159   if (success)\r
160   {\r
161     logger->log("Core", Log::INFO, "LED module initialised");\r
162   }\r
163   else\r
164   {\r
165     logger->log("Core", Log::EMERG, "LED module failed to initialise");\r
166     shutdown(1);\r
167         WSACleanup();\r
168         return 0;\r
169   }\r
170 \r
171   success = mtd->init("/dev/mtd1");\r
172   if (success)\r
173   {\r
174     logger->log("Core", Log::INFO, "Mtd module initialised");\r
175   }\r
176   else\r
177   {\r
178     logger->log("Core", Log::EMERG, "Mtd module failed to initialise");\r
179     shutdown(1);\r
180         WSACleanup();\r
181         return 0;\r
182   }\r
183 \r
184   success = timers->init();\r
185   if (success)\r
186   {\r
187     logger->log("Core", Log::INFO, "Timers module initialised");\r
188   }\r
189   else\r
190   {\r
191     logger->log("Core", Log::EMERG, "Timers module failed to initialise");\r
192     shutdown(1);\r
193         WSACleanup();\r
194         return 0;\r
195   }\r
196 \r
197   UCHAR videoFormat = (UCHAR)mtd->getPALorNTSC();\r
198   if      (videoFormat == Video::PAL)  logger->log("Core", Log::INFO, "Read from MTD: PAL 720x576");\r
199   else if (videoFormat == Video::NTSC) logger->log("Core", Log::INFO, "Read from MTD: NTSC 720x480");\r
200   else                                 logger->log("Core", Log::INFO, "No help from MTD. Assuming NTSC 720x480");\r
201 \r
202   success = video->init(videoFormat);\r
203   if (success)\r
204   {\r
205     logger->log("Core", Log::INFO, "Video module initialised");\r
206   }\r
207   else\r
208   {\r
209     logger->log("Core", Log::EMERG, "Video module failed to initialise");\r
210     shutdown(1);\r
211         WSACleanup();\r
212         return 0;\r
213   }\r
214 \r
215   success = osd->init((void*)&win);\r
216   if (success)\r
217   {\r
218     logger->log("Core", Log::INFO, "OSD module initialised");\r
219   }\r
220   else\r
221   {\r
222     logger->log("Core", Log::EMERG, "OSD module failed to initialise");\r
223     shutdown(1);\r
224         WSACleanup();\r
225         return 0;\r
226   }\r
227 \r
228   success = audio->init(Audio::MPEG2_PES);\r
229   if (success)\r
230   {\r
231     logger->log("Core", Log::INFO, "Audio module initialised");\r
232   }\r
233   else\r
234   {\r
235     logger->log("Core", Log::EMERG, "Audio module failed to initialise");\r
236     shutdown(1);\r
237         WSACleanup();\r
238         return 0;\r
239   }\r
240 \r
241   success = vdr->init(3024);\r
242   if (success)\r
243   {\r
244     logger->log("Core", Log::INFO, "VDR module initialised");\r
245   }\r
246   else\r
247   {\r
248     logger->log("Core", Log::EMERG, "VDR module failed to initialise");\r
249     shutdown(1);\r
250         WSACleanup();\r
251         return 0;\r
252   }\r
253 \r
254   success = viewman->init();\r
255   if (success)\r
256   {\r
257     logger->log("Core", Log::INFO, "ViewMan module initialised");\r
258   }\r
259   else\r
260   {\r
261     logger->log("Core", Log::EMERG, "ViewMan module failed to initialise");\r
262     shutdown(1);\r
263         WSACleanup();\r
264         return 0;\r
265   }\r
266 \r
267   success = command->init();\r
268   if (success)\r
269   {\r
270     logger->log("Core", Log::INFO, "Command module initialised");\r
271   }\r
272   else\r
273   {\r
274     logger->log("Core", Log::EMERG, "Command module failed to initialise");\r
275     shutdown(1);\r
276         WSACleanup();\r
277         return 0;\r
278   }\r
279 \r
280   // Other init ------------------------------------------------------------------------------------------------------\r
281 \r
282   logger->log("Core", Log::NOTICE, "Startup successful");\r
283 \r
284   // Run main loop ---------------------------------------------------------------------------------------------------\r
285 \r
286   // Ok, all major device components and other bits are loaded and ready\r
287   \r
288   HANDLE commandthread;\r
289  commandthread= CreateThread(NULL, 0, commandthreadStart, NULL,0, \r
290           NULL);\r
291   MSG message;\r
292   message.message=WM_NULL;\r
293   bool run=true;\r
294   while(run && WaitForSingleObject(commandthread,0)==WAIT_TIMEOUT) {\r
295           if (PeekMessage(&message, NULL, 0,0,PM_REMOVE)!=0) {\r
296                   if (TranslateAccelerator(win_main,acc,&message)==NULL) {\r
297                           TranslateMessage(&message);\r
298                           DispatchMessage(&message);\r
299                           switch (message.message) {\r
300                           case WM_QUIT:\r
301                                   run=false; //TODO post exit to command Messages\r
302                           };\r
303                   }\r
304           } else {\r
305                   //Render\r
306                   ((OsdWin*)osd)->Render();\r
307           }\r
308   }\r
309   // When that returns quit ------------------------------------------------------------------------------------------\r
310   WaitForSingleObject(commandthread,INFINITE);\r
311   shutdown(0);\r
312   WSACleanup();\r
313   return 0;\r
314 \r
315 }\r
316 \r
317 \r
318 \r
319 void CalculateWindowSize(RECT * size,ULONG size_mode) {\r
320         \r
321         DWORD width, height;\r
322         DWORD adjheight,adjwidth;\r
323         if (!wnd_fullscreen) {\r
324                 DWORD flags =WS_VISIBLE | WS_POPUP | WS_CAPTION | WS_SYSMENU \r
325                                  |WS_MINIMIZEBOX | WS_SIZEBOX |WS_MAXIMIZEBOX;\r
326                 RECT wnted={50,50,150,150};\r
327                 AdjustWindowRect(&wnted,flags ,false);\r
328                 adjwidth=-wnted.left+wnted.right-100;\r
329                 adjheight=-wnted.top+wnted.bottom-100;\r
330         } else {\r
331                 adjwidth=adjheight=0;\r
332         }\r
333         width=size->right-size->left-adjwidth;\r
334         height=size->bottom-size->top-adjheight;\r
335         UCHAR mode=video->getMode();\r
336         UCHAR aspect=((VideoWin*)video)->getAspectRatio();\r
337         UCHAR tvsize=((VideoWin*)video)->getPseudoTVsize();\r
338         double aspectrt=4./3.;\r
339         if (tvsize==Video::ASPECT16X9) {\r
340                 if (aspect==Video::ASPECT16X9) {\r
341                         aspectrt=4./3.; //looks strange, but it is a 16:9 tv\r
342                 } else if (aspect==Video::ASPECT4X3) {\r
343                         aspectrt=4./3./(16./9.)*(4./3.); //I hope this is correct\r
344                 }\r
345         } else if (tvsize==Video::ASPECT4X3) {\r
346                 if (aspect==Video::ASPECT16X9) {\r
347                         if (mode!=Video::NORMAL) {\r
348                                 aspectrt=16./9.;\r
349                         } else {\r
350                                 aspectrt=4./3.;\r
351                         }\r
352                 } else if (aspect==Video::ASPECT4X3) {\r
353                         aspectrt=4./3.;\r
354                 }\r
355         }\r
356         if (!wnd_fullscreen) {\r
357                 switch (size_mode) {\r
358                 case WMSZ_BOTTOM:\r
359                 case WMSZ_BOTTOMRIGHT:\r
360                 case WMSZ_TOP:\r
361                 case WMSZ_TOPRIGHT:\r
362                 width=(ULONG)(((double)height)*aspectrt);\r
363                 size->right=size->left+width+adjwidth;\r
364                 break;\r
365                 case WMSZ_BOTTOMLEFT:\r
366                 case WMSZ_TOPLEFT:\r
367                 width=(ULONG)(((double)height)*aspectrt);\r
368                 size->left=size->right-width-adjwidth;\r
369                 break;\r
370                 case WMSZ_LEFT:\r
371                 case WMSZ_RIGHT:\r
372                 height=(ULONG)(((double)width)/aspectrt);\r
373                 size->bottom=size->top+height+adjheight;\r
374                 break;\r
375                 }\r
376                 MoveWindow(win,0,0,width,height,TRUE);\r
377         } else {\r
378                 RECT newrect={0,0,width,height};\r
379                 DWORD newlength;\r
380                 if ((ULONG)(((double)height)*aspectrt)>width) {\r
381                         newlength=(ULONG)(((double)width)/aspectrt);\r
382                         newrect.top+=(height-newlength)/2;\r
383                         newrect.bottom-=(height-newlength);\r
384                 } else {\r
385                         newlength=(ULONG)(((double)height)*aspectrt);\r
386                         newrect.left+=(width-newlength)/2;\r
387                         newrect.right-=(width-newlength);\r
388                 }\r
389                 MoveWindow(win,newrect.left,newrect.top,newrect.right,newrect.bottom,TRUE);\r
390         }\r
391         \r
392 }\r
393 \r
394 void AdjustWindow() {\r
395         if (!wnd_fullscreen) {\r
396                 RECT winrect;\r
397                 GetWindowRect(win_main,&winrect);\r
398                 CalculateWindowSize(&winrect,WMSZ_BOTTOM);\r
399                 MoveWindow(win_main,winrect.left,\r
400                         winrect.top,winrect.right-winrect.left,winrect.bottom-winrect.top,true);\r
401         } else {\r
402                 RECT winrect;\r
403                 GetWindowRect(win_main,&winrect);\r
404                 CalculateWindowSize(&winrect,WMSZ_BOTTOM);\r
405 \r
406         }\r
407 }\r
408 \r
409 void ToggleFullscreen() {\r
410         if (wnd_fullscreen) {\r
411                 wnd_fullscreen=false;\r
412                 SetWindowLong(win_main,GWL_STYLE,WS_VISIBLE | WS_POPUP | WS_CAPTION | WS_SYSMENU \r
413                  |WS_MINIMIZEBOX | WS_SIZEBOX |WS_MAXIMIZEBOX);\r
414                 SetWindowPos(win_main,NULL,0,0,0,0,SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED);\r
415 \r
416                 SetWindowPos(win_main,HWND_TOP,wnd_fs_rect.left,wnd_fs_rect.top,\r
417                                                         wnd_fs_rect.right-wnd_fs_rect.left,\r
418                                                         wnd_fs_rect.bottom-wnd_fs_rect.top,\r
419                                                         SWP_DRAWFRAME | SWP_FRAMECHANGED);\r
420                 MoveWindow(win,wnd_fs_rect_client.left,wnd_fs_rect_client.top,\r
421                                                         wnd_fs_rect_client.right-wnd_fs_rect_client.left,\r
422                                                         wnd_fs_rect_client.bottom-wnd_fs_rect_client.top,TRUE);\r
423                 AdjustWindow();\r
424         } else {\r
425                 GetWindowRect(win_main,&wnd_fs_rect);\r
426                 GetWindowRect(win,&wnd_fs_rect_client);\r
427                 SetWindowLong(win_main,GWL_STYLE,WS_VISIBLE | WS_POPUP );\r
428                 SetWindowPos(win_main,NULL,0,0,0,0,SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED);\r
429                 HMONITOR monitor=MonitorFromWindow(win_main,MONITOR_DEFAULTTONEAREST);  \r
430                 MONITORINFO moninfo;\r
431                 moninfo.cbSize=sizeof(moninfo);\r
432                 wnd_fullscreen=true;\r
433                 if (!GetMonitorInfo(monitor,&moninfo)) return ;\r
434                 SetWindowPos(win_main,HWND_TOP,moninfo.rcMonitor.left,moninfo.rcMonitor.top,\r
435                         moninfo.rcMonitor.right,moninfo.rcMonitor.bottom,SWP_FRAMECHANGED);\r
436                 \r
437                 AdjustWindow();\r
438                 \r
439         }\r
440 \r
441 \r
442 }\r
443 \r
444 LONG FAR PASCAL WindowProc(HWND wind, UINT msg, WPARAM wparam, LPARAM lparam)\r
445 {\r
446    switch (msg) {\r
447    case WM_DESTROY: {\r
448            //TODO: call command\r
449            logger->log("Core", Log::NOTICE, "Window closed, shutting down...");\r
450         \r
451            ((RemoteWin*)Remote::getInstance())->SendPower();\r
452            PostQuitMessage(0);\r
453         }break;\r
454    case WM_SIZING: {\r
455            CalculateWindowSize((RECT*) lparam,wparam);\r
456            return TRUE;\r
457                                    }break;\r
458         case WM_SIZE: {\r
459         int width = LOWORD(lparam);\r
460         int height = HIWORD(lparam);\r
461          //Call device\r
462         }\r
463         break;\r
464          case WM_PAINT:\r
465         RECT r;\r
466         PAINTSTRUCT ps;\r
467         if (GetUpdateRect(wind, &r, FALSE)) {\r
468             BeginPaint(wind, &ps);\r
469             //Call Painting Mechanism\r
470             EndPaint(wind, &ps);\r
471         }\r
472         break;\r
473          case WM_KEYDOWN:\r
474                  if (((RemoteWin*)remote)->ReceiveButtonVK(wparam)) {\r
475                          return 0L; //We process that Key\r
476                  } else {\r
477                          return DefWindowProc(wind, msg, wparam, lparam);\r
478                  }\r
479 \r
480                  break;\r
481         case WM_APPCOMMAND:\r
482                 if (((RemoteWin*)remote)->ReceiveButtonAP(GET_APPCOMMAND_LPARAM(lparam))){\r
483                         return TRUE; //yes we process that message\r
484                 } else {\r
485                         return DefWindowProc(wind, msg, wparam, lparam);\r
486                 }\r
487 \r
488                 break;\r
489         case WM_COMMAND:\r
490                 if (LOWORD(wparam)==VOMP_FULL_SCREEN) {\r
491                         ToggleFullscreen();\r
492                         return 0;\r
493                 }\r
494                 if (((RemoteWin*)remote)->ReceiveButtonAP(LOWORD(wparam))){\r
495                         return 0; //yes we process that message\r
496                 } else {\r
497                         return DefWindowProc(wind, msg, wparam, lparam);\r
498                 }\r
499 \r
500                 break;\r
501         case WM_SETCURSOR:\r
502                 if (((HANDLE)wparam)==win) {\r
503                         SetCursor(NULL);\r
504                         return 1;\r
505                 } else {\r
506                         return DefWindowProc(wind, msg, wparam, lparam);\r
507                 }\r
508                 break;\r
509         case WM_SYSCOMMAND:\r
510                 if (wparam==SC_MAXIMIZE) {\r
511                         ToggleFullscreen();\r
512                         return 0;\r
513                 } else {\r
514                         return DefWindowProc(wind,msg,wparam, lparam);\r
515                 }\r
516                 break;\r
517     default:\r
518         return DefWindowProc(wind, msg, wparam, lparam);\r
519     }\r
520     return 0L;\r
521 }\r
522 \r
523 \r
524 bool InitApp(HINSTANCE hinst,int cmdshow) {\r
525         /* main window */\r
526         WNDCLASS wcs;\r
527         DWORD flags;\r
528         wcs.style = CS_HREDRAW | CS_VREDRAW;\r
529     wcs.lpfnWndProc = WindowProc;\r
530     wcs.cbClsExtra = 0;\r
531     wcs.cbWndExtra = sizeof(DWORD);\r
532     wcs.hInstance = hinst;\r
533     wcs.hIcon = NULL;\r
534     wcs.hCursor = NULL;\r
535     wcs.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);\r
536     wcs.lpszMenuName = NULL;\r
537     wcs.lpszClassName = "vomp";\r
538         acc=LoadAccelerators(hinst,MAKEINTRESOURCE(VOMPACCELERATOR));\r
539         if (!RegisterClass(&wcs))\r
540         return false;\r
541         flags =WS_VISIBLE | WS_POPUP | WS_CAPTION | WS_SYSMENU \r
542                  |WS_MINIMIZEBOX | WS_SIZEBOX |WS_MAXIMIZEBOX;\r
543         RECT wnted={50,50,768+50,576+50};\r
544         AdjustWindowRect(&wnted,flags ,false);\r
545         win_main=CreateWindow("vomp","VOMP on Windows",flags, CW_USEDEFAULT,CW_USEDEFAULT,\r
546                 wnted.right-wnted.left,wnted.bottom-wnted.top,NULL,NULL,hinst,NULL);\r
547         if (!win_main)\r
548         return FALSE;\r
549         ShowWindow(win_main,SW_SHOWNORMAL);\r
550     UpdateWindow(win_main);\r
551         /* in order to handle letterboxing we use a child window */\r
552         WNDCLASS child_wcs;\r
553         child_wcs.style = CS_HREDRAW | CS_VREDRAW;\r
554     child_wcs.lpfnWndProc = DefWindowProc;\r
555     child_wcs.cbClsExtra = 0;\r
556     child_wcs.cbWndExtra = sizeof(DWORD);\r
557     child_wcs.hInstance = hinst;\r
558     child_wcs.hIcon = NULL;\r
559     child_wcs.hCursor = NULL;\r
560     child_wcs.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);\r
561     child_wcs.lpszMenuName = NULL;\r
562     child_wcs.lpszClassName = "vomp_playback";\r
563         if (!RegisterClass(&child_wcs))\r
564         return false;\r
565 \r
566         win=CreateWindow("vomp_playback","Vomp Playback Window",WS_VISIBLE | WS_CHILD |WS_CLIPCHILDREN,\r
567                 0,0,768,576,win_main,NULL,hinst,NULL);\r
568         if (!win)\r
569                 return FALSE;\r
570         ShowWindow(win,SW_SHOWNORMAL);\r
571         UpdateWindow(win);\r
572         return TRUE;\r
573 }\r
574 \r
575 \r
576 \r
577 \r
578 \r
579 // -------------------------------------------------------------------------------------------------------------------\r
580 \r
581 void shutdown(int code)\r
582 {\r
583   if (viewman)\r
584   {\r
585     viewman->shutdown();\r
586     delete viewman;\r
587     logger->log("Core", Log::NOTICE, "ViewMan module shut down");\r
588   }\r
589 \r
590   if (command) // shut down command here in case views have posted messages\r
591   {\r
592     command->shutdown();\r
593     delete command;\r
594     logger->log("Core", Log::NOTICE, "Command module shut down");\r
595   }\r
596 \r
597   if (vdr)\r
598   {\r
599     vdr->shutdown();\r
600     delete vdr;\r
601     logger->log("Core", Log::NOTICE, "VDR module shut down");\r
602   }\r
603 \r
604   if (osd)\r
605   {\r
606     osd->shutdown();\r
607     delete osd;\r
608     logger->log("Core", Log::NOTICE, "OSD module shut down");\r
609   }\r
610 \r
611   if (audio)\r
612   {\r
613     audio->shutdown();\r
614     delete audio;\r
615     logger->log("Core", Log::NOTICE, "Audio module shut down");\r
616   }\r
617 \r
618   if (video)\r
619   {\r
620     video->shutdown();\r
621     delete video;\r
622     logger->log("Core", Log::NOTICE, "Video module shut down");\r
623   }\r
624 \r
625   if (timers)\r
626   {\r
627     timers->shutdown();\r
628     delete timers;\r
629     logger->log("Core", Log::NOTICE, "Timers module shut down");\r
630   }\r
631 \r
632   if (mtd)\r
633   {\r
634     mtd->shutdown();\r
635     delete mtd;\r
636     logger->log("Core", Log::NOTICE, "MTD module shut down");\r
637   }\r
638 \r
639   if (led)\r
640   {\r
641     led->shutdown();\r
642     delete led;\r
643     logger->log("Core", Log::NOTICE, "LED module shut down");\r
644   }\r
645 \r
646   if (remote)\r
647   {\r
648     remote->shutdown();\r
649     delete remote;\r
650     logger->log("Core", Log::NOTICE, "Remote module shut down");\r
651   }\r
652 \r
653   if (logger)\r
654   {\r
655     logger->log("Core", Log::NOTICE, "Log module shutting down... bye!\n\n");\r
656     logger->shutdown();\r
657     delete logger;\r
658   }\r
659   ExitProcess(0);\r
660 \r
661 }\r
662 \r
663 // -------------------------------------------------------------------------------------------------------------------\r
664 \r
665 ULLONG ntohll(ULLONG a)\r
666 {\r
667   return htonll(a);\r
668 }\r
669 \r
670 ULLONG htonll(ULLONG a)\r
671 {\r
672         return (((ULLONG)htonl((ULONG)((a<<32)>> 32))<<32) \r
673                 |(ULONG)htonl(((ULONG) (a >> 32))));\r
674 }\r
675 #endif\r