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