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