]> git.vomp.tv Git - vompclient.git/blob - winmain.cc
Split OsdWin into OsdWinPixel and WindowsOsd as preparation for Vector
[vompclient.git] / winmain.cc
1 /*
2     Copyright 2004-2005 Chris Tallon
3
4     This file is part of VOMP.
5
6     VOMP is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.
10
11     VOMP is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.
15
16     You should have received a copy of the GNU General Public License
17     along with VOMP; if not, write to the Free Software
18     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
19 */
20 #ifdef WIN32
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <signal.h>
25
26 #define _WIN32_WINNT 0x501
27 #include <winsock2.h>
28 #include <windows.h>
29
30 #include "vompreswin.h"
31
32 #include "defines.h"
33 #include "log.h"
34 #include "remotewin.h"
35 #include "ledwin.h"
36 #include "mtdwin.h"
37 #include "timers.h"
38 #include "videowin.h"
39 #include "audiowin.h"
40 #include "vdr.h"
41 #include "windowsosd.h"
42 #ifndef GRADIENT_DRAWING
43 #include "osdwinpixel.h"
44 #else
45
46 #endif
47 #include "boxstack.h"
48 #include "command.h"
49 #include "wol.h"
50 #include "vsleeptimer.h"
51
52 void sighandler(int signalReceived);
53 void shutdown(int code);
54
55 // Global variables --------------------------------------------------------------------------------------------------
56 int debugEnabled = 0;
57 Log* logger;
58 Remote* remote;
59 Mtd* mtd;
60 Led* led;
61 Osd* osd;
62 Timers* timers;
63 BoxStack* boxstack;
64 Command* command;
65 VDR* vdr;
66 Video* video;
67 Audio* audio;
68 Wol* wol;
69 Sleeptimer* sleeptimer;
70
71
72 bool wnd_fullscreen=false;
73 bool wnd_topmost=false;
74 RECT wnd_fs_rect={20,20,768+20,576+20};
75 RECT wnd_fs_rect_client={0,0,768,576};
76 //OSVERSIONINFO windows_ver; //attempt to distigsh windows versions
77 bool remotefnc=false;
78 HINSTANCE  hinstance;
79 bool cmenu=false;
80
81 HMODULE user32dll;
82 typedef UINT (WINAPI *GETRAWINPUTDATAFNC) (HRAWINPUT,UINT,LPVOID,PUINT,UINT);
83 typedef UINT (WINAPI *REGISTERRAWINPUTDEVICEFNC)  (PCRAWINPUTDEVICE,UINT,UINT);
84
85 GETRAWINPUTDATAFNC dynGetRawInputData=NULL;
86 REGISTERRAWINPUTDEVICEFNC dynRegisterRawInputDevices=NULL;
87
88 DWORD lastmousemove;
89
90
91 void MILLISLEEP(ULONG a)
92 {
93
94   Sleep(a);
95
96 }
97
98 int getClockRealTime(struct timespec *tp){
99         SYSTEMTIME systime;
100         __int64  filetime;
101         __int64  test;
102         GetSystemTime(&systime);
103         SystemTimeToFileTime(&systime, (FILETIME*)&filetime);
104         tp->tv_sec = (filetime - WINDOWS_TIME_BASE_OFFSET) / (10 * 1000 * 1000);
105         tp->tv_nsec = ((filetime - WINDOWS_TIME_BASE_OFFSET) % (10 * 1000 * 1000)) * 100;
106         return 0;
107 }
108
109 DWORD WINAPI commandthreadStart(void *arg)
110 {
111    command->run();
112    return 0;
113 }
114
115 void LoadRemoteFunctions() {
116   user32dll=LoadLibrary("user32.dll");
117   if (user32dll!=NULL) {
118     dynGetRawInputData=(GETRAWINPUTDATAFNC)GetProcAddress(user32dll,"GetRawInputData");
119     if (dynGetRawInputData!=NULL) {
120       dynRegisterRawInputDevices=(REGISTERRAWINPUTDEVICEFNC)GetProcAddress(user32dll,"RegisterRawInputDevices");
121       if (dynRegisterRawInputDevices!=NULL) {
122         remotefnc=true;
123       }
124     }
125   }
126 }
127
128 bool InitApp(HINSTANCE hinst,int cmdshow);
129
130 HWND win_main;//global window handle
131 HWND win;//global child window handle
132 HACCEL acc;
133
134 #define ERROR_MSG(str) MessageBox(win_main,str,"Error!",MB_OK|MB_ICONWARNING)
135 INT WINAPI WinMain( HINSTANCE hinst , HINSTANCE previnst, LPSTR cmdline, int cmdshow)
136 {
137   hinstance=hinst;
138   //On Windows we have to init a window, we use DXUT
139   LoadRemoteFunctions();
140   if (!InitApp(hinst,cmdshow)) return false;
141   //Starting Network support
142   WSADATA wsadat;
143   int result = WSAStartup(MAKEWORD(2,2),&wsadat);
144   if (result!=NO_ERROR) {
145         ERROR_MSG("Initialising WinSocked: Error at WSAStartup()\n");
146     return 0;
147   }
148
149   result= CoInitializeEx(NULL,COINIT_MULTITHREADED );//Initialize COM for DirectShow
150   if (result!=S_OK) {
151     ERROR_MSG("Initialising COM: Error at Coinitialize()\n");
152     return 0;
153   }
154
155
156
157
158   // Init global vars ------------------------------------------------------------------------------------------------
159
160   logger     = new Log();
161   remote     = new RemoteWin();
162   mtd        = new MtdWin();
163   led        = new LedWin();
164   timers     = new Timers();
165   osd        = new Osd_TYPE();
166   vdr        = new VDR();
167   video      = new VideoWin();
168   audio      = new AudioWin();
169   boxstack   = new BoxStack();
170   command    = new Command();
171   wol        = new Wol();
172   sleeptimer = new Sleeptimer();
173
174   if (!logger || !remote || !mtd || !led || !osd || !video || !audio || !boxstack || !command || !sleeptimer)
175   {
176     ERROR_MSG("Could not create objects. Memory problems?\n");
177     shutdown(1);
178   WSACleanup();
179   return 0;
180   }
181
182   // Get logging module started --------------------------------------------------------------------------------------
183
184   if (!logger->init(Log::DEBUG, "vompwin.log", true))
185   {
186     ERROR_MSG("Could not initialise log object. Aborting.\n");
187     shutdown(1);
188   WSACleanup();
189   return 0;
190   }
191
192   logger->log("Core", Log::INFO, "Starting up...");
193
194
195
196   // Init modules ----------------------------------------------------------------------------------------------------
197   int success;
198
199   success = remote->init("/dev/rawir");
200   if (success)
201   {
202     logger->log("Core", Log::INFO, "Remote module initialised");
203   }
204   else
205   {
206     logger->log("Core", Log::EMERG, "Remote module failed to initialise");
207     shutdown(1);
208   WSACleanup();
209   return 0;
210   }
211
212   success = led->init(0);
213   if (success)
214   {
215     logger->log("Core", Log::INFO, "LED module initialised");
216   }
217   else
218   {
219     logger->log("Core", Log::EMERG, "LED module failed to initialise");
220     shutdown(1);
221   WSACleanup();
222   return 0;
223   }
224
225   success = mtd->init();
226   if (success)
227   {
228     logger->log("Core", Log::INFO, "Mtd module initialised");
229   }
230   else
231   {
232     logger->log("Core", Log::EMERG, "Mtd module failed to initialise");
233     shutdown(1);
234   WSACleanup();
235   return 0;
236   }
237
238   success = timers->init();
239   if (success)
240   {
241     logger->log("Core", Log::INFO, "Timers module initialised");
242   }
243   else
244   {
245     logger->log("Core", Log::EMERG, "Timers module failed to initialise");
246     shutdown(1);
247   WSACleanup();
248   return 0;
249   }
250
251   UCHAR videoFormat = (UCHAR)mtd->getPALorNTSC();
252   if      (videoFormat == Video::PAL)  logger->log("Core", Log::INFO, "Read from MTD: PAL 720x576");
253   else if (videoFormat == Video::NTSC) logger->log("Core", Log::INFO, "Read from MTD: NTSC 720x480");
254   else                                 logger->log("Core", Log::INFO, "No help from MTD. Assuming NTSC 720x480");
255
256   success = video->init(videoFormat);
257   if (success)
258   {
259     logger->log("Core", Log::INFO, "Video module initialised");
260   }
261   else
262   {
263     logger->log("Core", Log::EMERG, "Video module failed to initialise");
264     shutdown(1);
265   WSACleanup();
266   return 0;
267   }
268
269   dynamic_cast<WindowsOsd*>(osd)->setWindow(win);
270   success = osd->init(NULL);
271   if (success)
272   {
273     logger->log("Core", Log::INFO, "OSD module initialised");
274   }
275   else
276   {
277     logger->log("Core", Log::EMERG, "OSD module failed to initialise");
278     shutdown(1);
279   WSACleanup();
280   return 0;
281   }
282
283   success = audio->init(Audio::MPEG2_PES);
284   if (success)
285   {
286     logger->log("Core", Log::INFO, "Audio module initialised");
287   }
288   else
289   {
290     logger->log("Core", Log::EMERG, "Audio module failed to initialise");
291     shutdown(1);
292   WSACleanup();
293   return 0;
294   }
295
296   success = vdr->init(3024);
297   if (success)
298   {
299     logger->log("Core", Log::INFO, "VDR module initialised");
300   }
301   else
302   {
303     logger->log("Core", Log::EMERG, "VDR module failed to initialise");
304     shutdown(1);
305   WSACleanup();
306   return 0;
307   }
308
309   success = boxstack->init();
310   if (success)
311   {
312     logger->log("Core", Log::INFO, "BoxStack module initialised");
313   }
314   else
315   {
316     logger->log("Core", Log::EMERG, "BoxStack module failed to initialise");
317     shutdown(1);
318   WSACleanup();
319   return 0;
320   }
321
322   success = command->init();
323   if (success)
324   {
325     logger->log("Core", Log::INFO, "Command module initialised");
326   }
327   else
328   {
329     logger->log("Core", Log::EMERG, "Command module failed to initialise");
330     shutdown(1);
331   WSACleanup();
332   return 0;
333   }
334
335   // Other init ------------------------------------------------------------------------------------------------------
336
337   logger->log("Core", Log::NOTICE, "Startup successful");
338
339   // Run main loop ---------------------------------------------------------------------------------------------------
340
341   // Ok, all major device components and other bits are loaded and ready
342   lastmousemove=timeGetTime();
343
344   HANDLE commandthread;
345  commandthread= CreateThread(NULL, 0, commandthreadStart, NULL,0,
346     NULL);
347   MSG message;
348   message.message=WM_NULL;
349   bool run=true;
350   while(run && WaitForSingleObject(commandthread,0)==WAIT_TIMEOUT) {
351     if (PeekMessage(&message, NULL, 0,0,PM_REMOVE)!=0) {
352       if (TranslateAccelerator(win_main,acc,&message)==NULL) {
353         TranslateMessage(&message);
354         DispatchMessage(&message);
355         switch (message.message) {
356         case WM_QUIT:
357           run=false; //TODO post exit to command Messages
358         };
359       }
360     } else {
361       //Render, moved to OSD !
362                 Sleep(20);
363       //((OsdWin*)osd)->Render();
364     }
365   }
366   // When that returns quit ------------------------------------------------------------------------------------------
367   WaitForSingleObject(commandthread,INFINITE);
368   shutdown(0);
369   WSACleanup();
370   if (user32dll) FreeModule(user32dll);
371   return 0;
372
373 }
374
375 bool TranslateMousePosition(POINT *pos) {
376
377   RECT clientrect;
378   ScreenToClient(win,pos);
379   GetClientRect(win,&clientrect);
380   if (!PtInRect(&clientrect,*pos)) return false;//Don't pass it further
381   pos->x=((double)pos->x)/((double) (clientrect.right-clientrect.left))
382     *((double)Video::getInstance()->getScreenWidth());
383   pos->y=((double)pos->y)/((double) (clientrect.bottom-clientrect.top))
384     *((double)Video::getInstance()->getScreenHeight());
385   return true;
386
387 }
388
389
390
391 void CalculateWindowSize(RECT * size,ULONG size_mode) {
392
393   DWORD width, height;
394   DWORD adjheight,adjwidth;
395   if (!wnd_fullscreen) {
396     DWORD flags =WS_VISIBLE | WS_POPUP | WS_CAPTION | WS_SYSMENU
397                |WS_MINIMIZEBOX | WS_SIZEBOX |WS_MAXIMIZEBOX;
398     RECT wnted={50,50,150,150};
399     AdjustWindowRect(&wnted,flags ,false);
400     adjwidth=-wnted.left+wnted.right-100;
401     adjheight=-wnted.top+wnted.bottom-100;
402   } else {
403     adjwidth=adjheight=0;
404   }
405   width=size->right-size->left-adjwidth;
406   height=size->bottom-size->top-adjheight;
407   UCHAR mode=Video::PAL;
408   UCHAR aspect=Video::ASPECT4X3;
409   UCHAR tvsize=Video::ASPECT4X3;
410   if (video) {
411       mode=video->getMode();
412       aspect=((VideoWin*)video)->getAspectRatio();
413       tvsize=((VideoWin*)video)->getPseudoTVsize();
414   }
415
416   double aspectrt=4./3.;
417   if (tvsize==Video::ASPECT16X9) {
418     if (aspect==Video::ASPECT16X9) {
419       aspectrt=4./3.; //looks strange, but it is a 16:9 tv
420     } else if (aspect==Video::ASPECT4X3) {
421       aspectrt=4./3./(16./9.)*(4./3.); //I hope this is correct
422     }
423   } else if (tvsize==Video::ASPECT4X3) {
424     if (aspect==Video::ASPECT16X9) {
425       if (mode!=Video::NORMAL) {
426         aspectrt=16./9.;
427       } else {
428         aspectrt=4./3.;
429       }
430     } else if (aspect==Video::ASPECT4X3) {
431       aspectrt=4./3.;
432     }
433   }
434   if (!wnd_fullscreen) {
435     switch (size_mode) {
436     case WMSZ_BOTTOM:
437     case WMSZ_BOTTOMRIGHT:
438     case WMSZ_TOP:
439     case WMSZ_TOPRIGHT:
440     width=(ULONG)(((double)height)*aspectrt);
441     size->right=size->left+width+adjwidth;
442     break;
443     case WMSZ_BOTTOMLEFT:
444     case WMSZ_TOPLEFT:
445     width=(ULONG)(((double)height)*aspectrt);
446     size->left=size->right-width-adjwidth;
447     break;
448     case WMSZ_LEFT:
449     case WMSZ_RIGHT:
450     height=(ULONG)(((double)width)/aspectrt);
451     size->bottom=size->top+height+adjheight;
452     break;
453     }
454     MoveWindow(win,0,0,width,height,TRUE);
455   } else {
456     RECT newrect={0,0,width,height};
457     DWORD newlength;
458     if ((ULONG)(((double)height)*aspectrt)>width) {
459       newlength=(ULONG)(((double)width)/aspectrt);
460       newrect.top+=(height-newlength)/2;
461       newrect.bottom-=(height-newlength);
462     } else {
463       newlength=(ULONG)(((double)height)*aspectrt);
464       newrect.left+=(width-newlength)/2;
465       newrect.right-=(width-newlength);
466     }
467     MoveWindow(win,newrect.left,newrect.top,newrect.right,newrect.bottom,TRUE);
468   }
469
470 }
471
472 void AdjustWindow() {
473   if (!wnd_fullscreen) {
474     RECT winrect;
475     GetWindowRect(win_main,&winrect);
476     CalculateWindowSize(&winrect,WMSZ_BOTTOM);
477     MoveWindow(win_main,winrect.left,
478       winrect.top,winrect.right-winrect.left,winrect.bottom-winrect.top,true);
479   } else {
480     RECT winrect;
481     GetWindowRect(win_main,&winrect);
482     CalculateWindowSize(&winrect,WMSZ_BOTTOM);
483
484   }
485 }
486
487 void ToggleFullscreen() {
488   if (wnd_fullscreen) {
489     wnd_fullscreen=false;
490     SetWindowLong(win_main,GWL_STYLE,WS_VISIBLE | WS_POPUP | WS_CAPTION | WS_SYSMENU
491                  |WS_MINIMIZEBOX | WS_SIZEBOX |WS_MAXIMIZEBOX);
492     SetWindowPos(win_main,NULL,0,0,0,0,SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED);
493
494     SetWindowPos(win_main,wnd_topmost?HWND_TOPMOST:HWND_TOP,wnd_fs_rect.left,wnd_fs_rect.top,
495               wnd_fs_rect.right-wnd_fs_rect.left,
496               wnd_fs_rect.bottom-wnd_fs_rect.top,
497               SWP_DRAWFRAME | SWP_FRAMECHANGED);
498     MoveWindow(win,wnd_fs_rect_client.left,wnd_fs_rect_client.top,
499               wnd_fs_rect_client.right-wnd_fs_rect_client.left,
500               wnd_fs_rect_client.bottom-wnd_fs_rect_client.top,TRUE);
501     AdjustWindow();
502   } else {
503     GetWindowRect(win_main,&wnd_fs_rect);
504     GetWindowRect(win,&wnd_fs_rect_client);
505     SetWindowLong(win_main,GWL_STYLE,WS_VISIBLE | WS_POPUP );
506     SetWindowPos(win_main,NULL,0,0,0,0,SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED);
507     HMONITOR monitor=MonitorFromWindow(win_main,MONITOR_DEFAULTTONEAREST);
508     MONITORINFO moninfo;
509     moninfo.cbSize=sizeof(moninfo);
510     wnd_fullscreen=true;
511     if (!GetMonitorInfo(monitor,&moninfo)) return ;
512     SetWindowPos(win_main,wnd_topmost?HWND_TOPMOST:HWND_TOP,moninfo.rcMonitor.left,moninfo.rcMonitor.top,
513       moninfo.rcMonitor.right,moninfo.rcMonitor.bottom,SWP_FRAMECHANGED);
514
515     AdjustWindow();
516
517   }
518
519
520 }
521
522 void ToggleTopmost() {
523   wnd_topmost=!wnd_topmost;
524   SetWindowPos(win_main,wnd_topmost?HWND_TOPMOST:HWND_NOTOPMOST,0,0,
525       0,0,SWP_NOMOVE | SWP_NOSIZE);
526 }
527
528 void CursorUpdate() {
529   POINT cursorpos;
530   GetCursorPos(&cursorpos);
531   HWND asswind;
532   asswind=WindowFromPoint(cursorpos);
533   if (asswind!=win_main && asswind!=win) {
534     return ; //not our responsibility
535   }
536   if ((timeGetTime()-lastmousemove)<4000 || cmenu) {
537     SetCursor(LoadCursor(NULL,IDC_ARROW));
538   } else {
539     SetCursor(NULL);
540   }
541 }
542
543 bool ContextMenu(HWND wind,int x,int y) {
544   POINT p={x,y};
545   RECT clientrect;
546   ScreenToClient(wind,&p);
547   GetClientRect(wind,&clientrect);
548   if (!PtInRect(&clientrect,p)) return false;
549   ClientToScreen(wind,&p);
550   HMENU menu;
551   HMENU popup;
552   menu=LoadMenu(hinstance,MAKEINTRESOURCE(VOMPMENU));
553   popup=GetSubMenu(menu,0);
554   if (wnd_fullscreen) {
555     CheckMenuItem(popup,VOMP_FULL_SCREEN,MF_BYCOMMAND|MF_CHECKED);
556   } else {
557     CheckMenuItem(popup,VOMP_FULL_SCREEN,MF_BYCOMMAND|MF_UNCHECKED);
558   }
559   if (wnd_topmost) {
560     CheckMenuItem(popup,VOMP_TOPMOST,MF_BYCOMMAND|MF_CHECKED);
561   } else {
562     CheckMenuItem(popup,VOMP_TOPMOST,MF_BYCOMMAND|MF_UNCHECKED);
563   }
564   cmenu=true;
565   TrackPopupMenu(popup,TPM_RIGHTBUTTON|TPM_LEFTALIGN,x,y,0,wind, NULL);
566   cmenu=false;
567
568
569   DestroyMenu(menu);
570   return true;
571 }
572
573 LONG FAR PASCAL WindowProc(HWND wind, UINT msg, WPARAM wparam, LPARAM lparam)
574 {
575
576    switch (msg) {
577    case WM_DESTROY: {
578      //TODO: call command
579      logger->log("Core", Log::NOTICE, "Window closed, shutting down...");
580
581      ((RemoteWin*)Remote::getInstance())->SendPower();
582      PostQuitMessage(0);
583   }break;
584    case WM_SIZING: {
585      CalculateWindowSize((RECT*) lparam,wparam);
586      return TRUE;
587            }break;
588   case WM_SIZE: {
589         int width = LOWORD(lparam);
590         int height = HIWORD(lparam);
591          //Call device
592         if (wparam == SIZE_MAXIMIZED) {
593             ToggleFullscreen();
594             return 0;
595         } /*else if (wparam == SIZE_MINIMIZED) {
596             ToggleFullscreen();
597             return 0;
598         }*/
599         //AdjustWindow();
600         }
601         break;
602    case WM_PAINT:
603         RECT r;
604         PAINTSTRUCT ps;
605         if (GetUpdateRect(wind, &r, FALSE)) {
606             BeginPaint(wind, &ps);
607             //Call Painting Mechanism
608             EndPaint(wind, &ps);
609         }
610         break;
611    case WM_KEYDOWN:
612      if (((RemoteWin*)remote)->ReceiveButtonVK(wparam)) {
613        return 0L; //We process that Key
614      } else {
615        return DefWindowProc(wind, msg, wparam, lparam);
616      }
617
618      break;
619      case WM_CHAR:
620      if (((RemoteWin*)remote)->ReceiveButtonCH(wparam)) {
621        return 0L; //We process that Key
622      } else {
623        return DefWindowProc(wind, msg, wparam, lparam);
624      }
625
626      break;
627   case WM_APPCOMMAND:
628     if (((RemoteWin*)remote)->ReceiveButtonAP(GET_APPCOMMAND_LPARAM(lparam))){
629       return TRUE; //yes we process that message
630     } else {
631       return DefWindowProc(wind, msg, wparam, lparam);
632     }
633
634     break;
635   case WM_INPUT:
636     if (remotefnc ) {
637       //only on XP!
638        LPRAWINPUT lpit;
639        UINT risize;
640        dynGetRawInputData((HRAWINPUT)lparam,RID_INPUT,NULL,&risize,sizeof(RAWINPUTHEADER));
641        lpit=(LPRAWINPUT)malloc(risize);
642        dynGetRawInputData((HRAWINPUT)lparam,RID_INPUT,lpit,&risize,sizeof(RAWINPUTHEADER));
643
644       if (lpit->header.dwType==RIM_TYPEHID && lpit->data.hid.dwSizeHid>=2) {
645         DWORD button=lpit->data.hid.bRawData[1] | (lpit->data.hid.bRawData[0]<< 8);
646         if (((RemoteWin*)remote)->ReceiveButtonRI(button)){
647           free(lpit);
648           return 0; //yes we process that message
649         }
650       }
651       free(lpit);
652     }
653     return DefWindowProc(wind, msg, wparam, lparam);
654
655
656     break;
657   case WM_COMMAND:
658     if (LOWORD(wparam)==VOMP_FULL_SCREEN) {
659       ToggleFullscreen();
660       return 0;
661     }
662     if (LOWORD(wparam)==VOMP_TOPMOST) {
663       ToggleTopmost();
664       return 0;
665     }
666     if (((RemoteWin*)remote)->ReceiveButtonAP(LOWORD(wparam))){
667       return 0; //yes we process that message
668     } else {
669       return DefWindowProc(wind, msg, wparam, lparam);
670     }
671
672     break;
673   case WM_SETCURSOR:
674     if (((HANDLE)wparam)==win) {
675       CursorUpdate();
676       return 1;
677     } else {
678       return DefWindowProc(wind, msg, wparam, lparam);
679     }
680     break;
681   case WM_SYSCOMMAND:
682     if (wparam==SC_MAXIMIZE) {
683       ToggleFullscreen();
684       return 0;
685     } else if (wparam==SC_SCREENSAVE || wparam==SC_MONITORPOWER) {
686       return 0;
687     } else {
688       return DefWindowProc(wind,msg,wparam, lparam);
689     }
690     break;
691   case WM_MOUSEMOVE: {
692
693     lastmousemove=timeGetTime();
694     SetCursor(LoadCursor(NULL,IDC_ARROW));
695     SetTimer(wind,VOMP_CURSORUPDATE,4500,NULL);
696     POINT mpos={GET_X_LPARAM(lparam),GET_Y_LPARAM(lparam)};
697     ClientToScreen(wind,&mpos);
698     if (TranslateMousePosition(&mpos)) {
699       Message *mousemes=new Message();
700       mousemes->message=Message::MOUSE_MOVE;
701       mousemes->from=NULL;
702       mousemes->to=BoxStack::getInstance();
703       mousemes->parameter=(mpos.x & 0xFFFF)<< 16| (mpos.y & 0xFFFF);
704       mousemes->tag=0;
705       //command->postMessageFromOuterSpace(mousemes);
706       command->postMessageIfNotBusy(mousemes);
707     }
708
709     return 0;
710     //return DefWindowProc(wind,msg,wparam, lparam);
711              }
712     break;
713   case WM_TIMER:
714     if (wparam==VOMP_CURSORUPDATE) {
715       CursorUpdate();
716       return 0;
717     }
718     return DefWindowProc(wind, msg, wparam, lparam);
719
720     break;
721   case WM_CONTEXTMENU:
722     if (!ContextMenu(wind,GET_X_LPARAM(lparam),GET_Y_LPARAM(lparam))) {
723       return DefWindowProc(wind, msg, wparam, lparam);
724     } else {
725       return 0;
726     }
727     break;
728   case WM_LBUTTONDOWN:{
729     POINT mpos={GET_X_LPARAM(lparam),GET_Y_LPARAM(lparam)};
730     ClientToScreen(wind,&mpos);
731     if (TranslateMousePosition(&mpos)) {
732       Message *mousemes=new Message();
733       mousemes->message=Message::MOUSE_LBDOWN;
734       mousemes->from=NULL;
735       mousemes->to=BoxStack::getInstance();
736       mousemes->parameter=(mpos.x & 0xFFFF)<< 16| (mpos.y & 0xFFFF);
737       mousemes->tag=0;
738       command->postMessageFromOuterSpace(mousemes);
739     }
740             }break;
741   case WM_MOUSEWHEEL:{
742         POINT mpos = { GET_X_LPARAM(lparam), GET_Y_LPARAM(lparam) };
743         ClientToScreen(wind, &mpos);
744         if (TranslateMousePosition(&mpos)) {
745                 Message *mousemes = new Message();
746                 mousemes->message = Message::MOUSE_SCROLL;
747                 mousemes->from = NULL;
748                 mousemes->to = BoxStack::getInstance();
749                 mousemes->parameter = (0 & 0xFFFF) << 16 | (GET_WHEEL_DELTA_WPARAM(wparam)  &0xFFFF);
750                 mousemes->tag = (mpos.x & 0xFFFF) << 16 | (mpos.y & 0xFFFF);
751                 command->postMessageFromOuterSpace(mousemes);
752         }
753
754   } break;
755     default:
756         return DefWindowProc(wind, msg, wparam, lparam);
757     }
758     return 0L;
759 }
760
761
762 bool InitApp(HINSTANCE hinst,int cmdshow) {
763   /* main window */
764   WNDCLASS wcs;
765   DWORD flags;
766   wcs.style = CS_HREDRAW | CS_VREDRAW;
767     wcs.lpfnWndProc = WindowProc;
768     wcs.cbClsExtra = 0;
769     wcs.cbWndExtra = sizeof(DWORD);
770     wcs.hInstance = hinst;
771     wcs.hIcon = NULL;
772     wcs.hCursor = NULL;
773     wcs.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
774     wcs.lpszMenuName = NULL;
775     wcs.lpszClassName = "vomp";
776   acc=LoadAccelerators(hinst,MAKEINTRESOURCE(VOMPACCELERATOR));
777   if (!RegisterClass(&wcs))
778         return false;
779   flags =WS_VISIBLE | WS_POPUP | WS_CAPTION | WS_SYSMENU
780                  |WS_MINIMIZEBOX | WS_SIZEBOX |WS_MAXIMIZEBOX;
781   RECT wnted={50,50,768+50,576+50};
782   AdjustWindowRect(&wnted,flags ,false);
783   win_main=CreateWindow("vomp","VOMP on Windows",flags, CW_USEDEFAULT,CW_USEDEFAULT,
784     wnted.right-wnted.left,wnted.bottom-wnted.top,NULL,NULL,hinst,NULL);
785   if (!win_main)
786         return FALSE;
787   ShowWindow(win_main,SW_SHOWNORMAL);
788     UpdateWindow(win_main);
789   /* in order to handle letterboxing we use a child window */
790   WNDCLASS child_wcs;
791   child_wcs.style = CS_HREDRAW | CS_VREDRAW;
792     child_wcs.lpfnWndProc = WindowProc;
793     child_wcs.cbClsExtra = 0;
794     child_wcs.cbWndExtra = sizeof(DWORD);
795     child_wcs.hInstance = hinst;
796     child_wcs.hIcon = NULL;
797     child_wcs.hCursor = NULL;
798     child_wcs.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
799     child_wcs.lpszMenuName = NULL;
800     child_wcs.lpszClassName = "vomp_playback";
801   if (!RegisterClass(&child_wcs))
802         return false;
803
804   win=CreateWindow("vomp_playback","Vomp Playback Window",WS_VISIBLE | WS_CHILD |WS_CLIPCHILDREN,
805     0,0,768,576,win_main,NULL,hinst,NULL);
806   if (!win)
807     return FALSE;
808   ShowWindow(win,SW_SHOWNORMAL);
809   UpdateWindow(win);
810   if (remotefnc) {//at least windows XP
811     /* We want to support MCE Remote controls*/
812     RAWINPUTDEVICE remote_control_data[4];
813     ZeroMemory(remote_control_data,sizeof(remote_control_data));
814     remote_control_data[0].usUsagePage=0xFFBC;
815     remote_control_data[0].usUsage=0x88;
816     remote_control_data[0].dwFlags=0;
817     remote_control_data[1].usUsagePage=0x0C;
818     remote_control_data[1].usUsage=0x80;
819     remote_control_data[1].dwFlags=0;
820     remote_control_data[2].usUsagePage=0x0C;
821     remote_control_data[2].usUsage=0x01;
822     remote_control_data[2].dwFlags=0;
823     remote_control_data[3].usUsagePage=0x01;
824     remote_control_data[3].usUsage=0x80;
825     remote_control_data[3].dwFlags=0;
826     if (dynRegisterRawInputDevices(remote_control_data,4,sizeof(remote_control_data[0]))!=TRUE) {
827       MessageBox(0,"Registering remote control failed!","Aborting!",0);
828       return FALSE;
829     }
830
831   }
832   return TRUE;
833 }
834
835
836
837
838
839 // -------------------------------------------------------------------------------------------------------------------
840
841 void shutdown(int code)
842 {
843   if (boxstack)
844   {
845     boxstack->shutdown();
846     delete boxstack;
847     logger->log("Core", Log::NOTICE, "BoxStack module shut down");
848   }
849
850   if (command) // shut down command here in case views have posted messages
851   {
852     command->shutdown();
853     delete command;
854     logger->log("Core", Log::NOTICE, "Command module shut down");
855   }
856
857   if (vdr)
858   {
859     vdr->shutdown();
860     delete vdr;
861     logger->log("Core", Log::NOTICE, "VDR module shut down");
862   }
863
864   if (osd)
865   {
866     osd->shutdown();
867     delete osd;
868     logger->log("Core", Log::NOTICE, "OSD module shut down");
869   }
870
871   if (audio)
872   {
873     audio->shutdown();
874     delete audio;
875     logger->log("Core", Log::NOTICE, "Audio module shut down");
876   }
877
878   if (video)
879   {
880     video->shutdown();
881     delete video;
882     logger->log("Core", Log::NOTICE, "Video module shut down");
883   }
884
885   if (timers)
886   {
887     timers->shutdown();
888     delete timers;
889     logger->log("Core", Log::NOTICE, "Timers module shut down");
890   }
891
892   if (mtd)
893   {
894     mtd->shutdown();
895     delete mtd;
896     logger->log("Core", Log::NOTICE, "MTD module shut down");
897   }
898
899   if (led)
900   {
901     led->shutdown();
902     delete led;
903     logger->log("Core", Log::NOTICE, "LED module shut down");
904   }
905
906   if (remote)
907   {
908     remote->shutdown();
909     delete remote;
910     logger->log("Core", Log::NOTICE, "Remote module shut down");
911   }
912   if (wol)
913   {
914     delete wol;
915     logger->log("Core", Log::NOTICE, "WOL module shut down");
916   }
917
918   if (logger)
919   {
920     logger->log("Core", Log::NOTICE, "Log module shutting down... bye!\n\n");
921     logger->shutdown();
922     delete logger;
923   }
924   if (sleeptimer)
925   {
926     delete sleeptimer;
927     logger->log("Core", Log::NOTICE, "Sleeptimer module shut down");
928   }
929   ExitProcess(0);
930
931 }
932
933 // -------------------------------------------------------------------------------------------------------------------
934
935 ULLONG htonll(ULLONG a)
936 {
937   return (((ULLONG)htonl((ULONG)((a<<32)>> 32))<<32)
938     |(ULONG)htonl(((ULONG) (a >> 32))));
939 }
940
941 ULLONG ntohll(ULLONG a)
942 {
943   return htonll(a);
944 }
945
946 #endif
947