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