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