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