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