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