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