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