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