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