]> git.vomp.tv Git - vompclient.git/blob - winmain.cc
MTD interface change
[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_APPCOMMAND:
580     if (((RemoteWin*)remote)->ReceiveButtonAP(GET_APPCOMMAND_LPARAM(lparam))){
581       return TRUE; //yes we process that message
582     } else {
583       return DefWindowProc(wind, msg, wparam, lparam);
584     }
585
586     break;
587   case WM_INPUT:
588     if (remotefnc ) {
589       //only on XP!
590        LPRAWINPUT lpit;
591        UINT risize;
592        dynGetRawInputData((HRAWINPUT)lparam,RID_INPUT,NULL,&risize,sizeof(RAWINPUTHEADER));
593        lpit=(LPRAWINPUT)malloc(risize);
594        dynGetRawInputData((HRAWINPUT)lparam,RID_INPUT,lpit,&risize,sizeof(RAWINPUTHEADER));
595
596       if (lpit->header.dwType==RIM_TYPEHID && lpit->data.hid.dwSizeHid>=2) {
597         DWORD button=lpit->data.hid.bRawData[1] | (lpit->data.hid.bRawData[0]<< 8);
598         if (((RemoteWin*)remote)->ReceiveButtonRI(button)){
599           free(lpit);
600           return 0; //yes we process that message
601         }
602       }
603       free(lpit);
604     }
605     return DefWindowProc(wind, msg, wparam, lparam);
606
607
608     break;
609   case WM_COMMAND:
610     if (LOWORD(wparam)==VOMP_FULL_SCREEN) {
611       ToggleFullscreen();
612       return 0;
613     }
614     if (LOWORD(wparam)==VOMP_TOPMOST) {
615       ToggleTopmost();
616       return 0;
617     }
618     if (((RemoteWin*)remote)->ReceiveButtonAP(LOWORD(wparam))){
619       return 0; //yes we process that message
620     } else {
621       return DefWindowProc(wind, msg, wparam, lparam);
622     }
623
624     break;
625   case WM_SETCURSOR:
626     if (((HANDLE)wparam)==win) {
627       CursorUpdate();
628       return 1;
629     } else {
630       return DefWindowProc(wind, msg, wparam, lparam);
631     }
632     break;
633   case WM_SYSCOMMAND:
634     if (wparam==SC_MAXIMIZE) {
635       ToggleFullscreen();
636       return 0;
637     } else if (wparam==SC_SCREENSAVE || wparam==SC_MONITORPOWER) {
638       return 0;
639     } else {
640       return DefWindowProc(wind,msg,wparam, lparam);
641     }
642     break;
643   case WM_MOUSEMOVE: {
644
645     lastmousemove=timeGetTime();
646     SetCursor(LoadCursor(NULL,IDC_ARROW));
647     SetTimer(wind,VOMP_CURSORUPDATE,4500,NULL);
648     POINT mpos={GET_X_LPARAM(lparam),GET_Y_LPARAM(lparam)};
649     ClientToScreen(wind,&mpos);
650     if (TranslateMousePosition(&mpos)) {
651       Message *mousemes=new Message();
652       mousemes->message=Message::MOUSE_MOVE;
653       mousemes->from=NULL;
654       mousemes->to=ViewMan::getInstance();
655       mousemes->parameter=(mpos.x & 0xFFFF)<< 16| (mpos.y & 0xFFFF);
656       mousemes->tag=0;
657       //command->postMessageFromOuterSpace(mousemes);
658       command->postMessageIfNotBusy(mousemes);
659     }
660
661     return 0;
662     //return DefWindowProc(wind,msg,wparam, lparam);
663              }
664     break;
665   case WM_TIMER:
666     if (wparam==VOMP_CURSORUPDATE) {
667       CursorUpdate();
668       return 0;
669     }
670     return DefWindowProc(wind, msg, wparam, lparam);
671
672     break;
673   case WM_CONTEXTMENU:
674     if (!ContextMenu(wind,GET_X_LPARAM(lparam),GET_Y_LPARAM(lparam))) {
675       return DefWindowProc(wind, msg, wparam, lparam);
676     } else {
677       return 0;
678     }
679     break;
680   case WM_LBUTTONDOWN:{
681     POINT mpos={GET_X_LPARAM(lparam),GET_Y_LPARAM(lparam)};
682     ClientToScreen(wind,&mpos);
683     if (TranslateMousePosition(&mpos)) {
684       Message *mousemes=new Message();
685       mousemes->message=Message::MOUSE_LBDOWN;
686       mousemes->from=NULL;
687       mousemes->to=ViewMan::getInstance();
688       mousemes->parameter=(mpos.x & 0xFFFF)<< 16| (mpos.y & 0xFFFF);
689       mousemes->tag=0;
690       command->postMessageFromOuterSpace(mousemes);
691     }
692             }break;
693     default:
694         return DefWindowProc(wind, msg, wparam, lparam);
695     }
696     return 0L;
697 }
698
699
700 bool InitApp(HINSTANCE hinst,int cmdshow) {
701   /* main window */
702   WNDCLASS wcs;
703   DWORD flags;
704   wcs.style = CS_HREDRAW | CS_VREDRAW;
705     wcs.lpfnWndProc = WindowProc;
706     wcs.cbClsExtra = 0;
707     wcs.cbWndExtra = sizeof(DWORD);
708     wcs.hInstance = hinst;
709     wcs.hIcon = NULL;
710     wcs.hCursor = NULL;
711     wcs.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
712     wcs.lpszMenuName = NULL;
713     wcs.lpszClassName = "vomp";
714   acc=LoadAccelerators(hinst,MAKEINTRESOURCE(VOMPACCELERATOR));
715   if (!RegisterClass(&wcs))
716         return false;
717   flags =WS_VISIBLE | WS_POPUP | WS_CAPTION | WS_SYSMENU
718                  |WS_MINIMIZEBOX | WS_SIZEBOX |WS_MAXIMIZEBOX;
719   RECT wnted={50,50,768+50,576+50};
720   AdjustWindowRect(&wnted,flags ,false);
721   win_main=CreateWindow("vomp","VOMP on Windows",flags, CW_USEDEFAULT,CW_USEDEFAULT,
722     wnted.right-wnted.left,wnted.bottom-wnted.top,NULL,NULL,hinst,NULL);
723   if (!win_main)
724         return FALSE;
725   ShowWindow(win_main,SW_SHOWNORMAL);
726     UpdateWindow(win_main);
727   /* in order to handle letterboxing we use a child window */
728   WNDCLASS child_wcs;
729   child_wcs.style = CS_HREDRAW | CS_VREDRAW;
730     child_wcs.lpfnWndProc = WindowProc;
731     child_wcs.cbClsExtra = 0;
732     child_wcs.cbWndExtra = sizeof(DWORD);
733     child_wcs.hInstance = hinst;
734     child_wcs.hIcon = NULL;
735     child_wcs.hCursor = NULL;
736     child_wcs.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
737     child_wcs.lpszMenuName = NULL;
738     child_wcs.lpszClassName = "vomp_playback";
739   if (!RegisterClass(&child_wcs))
740         return false;
741
742   win=CreateWindow("vomp_playback","Vomp Playback Window",WS_VISIBLE | WS_CHILD |WS_CLIPCHILDREN,
743     0,0,768,576,win_main,NULL,hinst,NULL);
744   if (!win)
745     return FALSE;
746   ShowWindow(win,SW_SHOWNORMAL);
747   UpdateWindow(win);
748   if (remotefnc) {//at least windows XP
749     /* We want to support MCE Remote controls*/
750     RAWINPUTDEVICE remote_control_data[4];
751     ZeroMemory(remote_control_data,sizeof(remote_control_data));
752     remote_control_data[0].usUsagePage=0xFFBC;
753     remote_control_data[0].usUsage=0x88;
754     remote_control_data[0].dwFlags=0;
755     remote_control_data[1].usUsagePage=0x0C;
756     remote_control_data[1].usUsage=0x80;
757     remote_control_data[1].dwFlags=0;
758     remote_control_data[2].usUsagePage=0x0C;
759     remote_control_data[2].usUsage=0x01;
760     remote_control_data[2].dwFlags=0;
761     remote_control_data[3].usUsagePage=0x01;
762     remote_control_data[3].usUsage=0x80;
763     remote_control_data[3].dwFlags=0;
764     if (dynRegisterRawInputDevices(remote_control_data,4,sizeof(remote_control_data[0]))!=TRUE) {
765       MessageBox(0,"Registering remote control failed!","Aborting!",0);
766       return FALSE;
767     }
768
769   }
770   return TRUE;
771 }
772
773
774
775
776
777 // -------------------------------------------------------------------------------------------------------------------
778
779 void shutdown(int code)
780 {
781   if (viewman)
782   {
783     viewman->shutdown();
784     delete viewman;
785     logger->log("Core", Log::NOTICE, "ViewMan module shut down");
786   }
787
788   if (command) // shut down command here in case views have posted messages
789   {
790     command->shutdown();
791     delete command;
792     logger->log("Core", Log::NOTICE, "Command module shut down");
793   }
794
795   if (vdr)
796   {
797     vdr->shutdown();
798     delete vdr;
799     logger->log("Core", Log::NOTICE, "VDR module shut down");
800   }
801
802   if (osd)
803   {
804     osd->shutdown();
805     delete osd;
806     logger->log("Core", Log::NOTICE, "OSD module shut down");
807   }
808
809   if (audio)
810   {
811     audio->shutdown();
812     delete audio;
813     logger->log("Core", Log::NOTICE, "Audio module shut down");
814   }
815
816   if (video)
817   {
818     video->shutdown();
819     delete video;
820     logger->log("Core", Log::NOTICE, "Video module shut down");
821   }
822
823   if (timers)
824   {
825     timers->shutdown();
826     delete timers;
827     logger->log("Core", Log::NOTICE, "Timers module shut down");
828   }
829
830   if (mtd)
831   {
832     mtd->shutdown();
833     delete mtd;
834     logger->log("Core", Log::NOTICE, "MTD module shut down");
835   }
836
837   if (led)
838   {
839     led->shutdown();
840     delete led;
841     logger->log("Core", Log::NOTICE, "LED module shut down");
842   }
843
844   if (remote)
845   {
846     remote->shutdown();
847     delete remote;
848     logger->log("Core", Log::NOTICE, "Remote module shut down");
849   }
850
851   if (logger)
852   {
853     logger->log("Core", Log::NOTICE, "Log module shutting down... bye!\n\n");
854     logger->shutdown();
855     delete logger;
856   }
857   ExitProcess(0);
858
859 }
860
861 // -------------------------------------------------------------------------------------------------------------------
862
863 ULLONG ntohll(ULLONG a)
864 {
865   return htonll(a);
866 }
867
868 ULLONG htonll(ULLONG a)
869 {
870   return (((ULLONG)htonl((ULONG)((a<<32)>> 32))<<32)
871     |(ULONG)htonl(((ULONG) (a >> 32))));
872 }
873 #endif