VirtualBox

source: vbox/trunk/src/VBox/Frontends/VBoxFB/VBoxFB.cpp@ 13643

Last change on this file since 13643 was 11662, checked in by vboxsync, 16 years ago

Build fixes for PutScancodes

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 20.9 KB
Line 
1/** @file
2 *
3 * VBox frontends: Framebuffer (FB, DirectFB):
4 * main() routine
5 */
6
7/*
8 * Copyright (C) 2006-2007 Sun Microsystems, Inc.
9 *
10 * This file is part of VirtualBox Open Source Edition (OSE), as
11 * available from http://www.virtualbox.org. This file is free software;
12 * you can redistribute it and/or modify it under the terms of the GNU
13 * General Public License (GPL) as published by the Free Software
14 * Foundation, in version 2 as it comes in the "COPYING" file of the
15 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
16 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
17 *
18 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
19 * Clara, CA 95054 USA or visit http://www.sun.com if you need
20 * additional information or have any questions.
21 */
22
23#include "VBoxFB.h"
24#include "Framebuffer.h"
25#include <getopt.h>
26#include <VBox/param.h>
27#include <iprt/path.h>
28
29/**
30 * Globals
31 */
32uint32_t useFixedVideoMode = 0;
33int scaleGuest = 0;
34videoMode fixedVideoMode = {0};
35int32_t initialVideoMode = -1;
36
37void showusage()
38{
39 printf("\nThe following parameters are supported:\n"
40 "--startvm uuid start VM with UUID 'uuid'\n"
41 "--fixedres WxHxBPP always use fixed host resolution\n"
42 "--listhostmodes display list of suported host display modes and exit\n"
43 "--scale scale guest video mode to host video mode\n"
44 "--nodirectblit disable direct blitting, use intermediate framebuffer\n"
45 "--showlabel show VM name on top of the VM display\n");
46}
47
48/** entry point */
49int main(int argc, char *argv[])
50{
51 nsID uuid;
52 int c;
53 int listHostModes = 0;
54 int quit = 0;
55 const struct option options[] =
56 {
57 { "help", no_argument, NULL, 'h' },
58 { "startvm", required_argument, NULL, 's' },
59 { "fixedres", required_argument, NULL, 'f' },
60 { "listhostmodes", no_argument, NULL, 'l' },
61 { "scale", no_argument, NULL, 'c' }
62 };
63
64 printf("VirtualBox DirectFB GUI built %s %s\n"
65 "(C) 2004-2008 Sun Microsystems, Inc.\n"
66 "(C) 2004-2005 secunet Security Networks AG\n", __DATE__, __TIME__);
67
68 RTUuidClear((PRTUUID)&uuid);
69
70 for (;;)
71 {
72 c = getopt_long(argc, argv, "s:", options, NULL);
73 if (c == -1)
74 break;
75 switch (c)
76 {
77 case 'h':
78 {
79 showusage();
80 exit(0);
81 break;
82 }
83 case 's':
84 {
85 // UUID as string, parse it
86 if (!VBOX_SUCCESS(RTUuidFromStr((PRTUUID)&uuid, optarg)))
87 {
88 printf("Error, invalid UUID format given!\n");
89 showusage();
90 exit(-1);
91 }
92 break;
93 }
94 case 'f':
95 {
96 if (sscanf(optarg, "%ux%ux%u", &fixedVideoMode.width, &fixedVideoMode.height,
97 &fixedVideoMode.bpp) != 3)
98 {
99 printf("Error, invalid resolution argument!\n");
100 showusage();
101 exit(-1);
102 }
103 useFixedVideoMode = 1;
104 break;
105 }
106 case 'l':
107 {
108 listHostModes = 1;
109 break;
110 }
111 case 'c':
112 {
113 scaleGuest = 1;
114 break;
115 }
116 default:
117 break;
118 }
119 }
120
121 // check if we got a UUID
122 if (RTUuidIsNull((PRTUUID)&uuid))
123 {
124 printf("Error, no UUID given!\n");
125 showusage();
126 exit(-1);
127 }
128
129
130 /**
131 * XPCOM setup
132 */
133
134 nsresult rc;
135 XPCOMGlueStartup(nsnull);
136
137 // get the path to the executable
138 char appPath [RTPATH_MAX];
139 RTPathProgram (appPath, RTPATH_MAX);
140
141 nsCOMPtr<nsIFile> nsAppPath;
142 {
143 nsCOMPtr<nsILocalFile> file;
144 rc = NS_NewNativeLocalFile(nsEmbedCString (appPath), PR_FALSE,
145 getter_AddRefs (file));
146 if (NS_SUCCEEDED(rc))
147 {
148 nsAppPath = do_QueryInterface(file, &rc);
149 }
150 }
151 if (NS_FAILED(rc))
152 {
153 printf ("Error: failed to create file object! (rc=%08X)\n", rc);
154 exit(-1);
155 }
156
157 nsCOMPtr<nsIServiceManager> serviceManager;
158 rc = NS_InitXPCOM2(getter_AddRefs(serviceManager), nsAppPath, nsnull);
159 if (NS_FAILED(rc))
160 {
161 printf("Error: XPCOM could not be initialized! rc=0x%x\n", rc);
162 exit(-1);
163 }
164
165 // register our component
166 nsCOMPtr<nsIComponentRegistrar> registrar = do_QueryInterface(serviceManager);
167 if (!registrar)
168 {
169 printf("Error: could not query nsIComponentRegistrar interface!\n");
170 exit(-1);
171 }
172 registrar->AutoRegister(nsnull);
173
174 nsCOMPtr<ipcIService> ipcServ = do_GetService(IPC_SERVICE_CONTRACTID, &rc);
175 if (NS_FAILED(rc))
176 {
177 printf("Error: could not get IPC service! rc = %08X\n", rc);
178 exit(-1);
179 }
180
181 nsCOMPtr<ipcIDConnectService> dcon = do_GetService(IPC_DCONNECTSERVICE_CONTRACTID, &rc);
182 if (NS_FAILED(rc))
183 {
184 printf("Error: could not get DCONNECT service! rc = %08X\n", rc);
185 exit(-1);
186 }
187
188 PRUint32 serverID = 0;
189 rc = ipcServ->ResolveClientName("VirtualBoxServer", &serverID);
190 if (NS_FAILED(rc))
191 {
192 printf("Error: could not get VirtualBox server ID! rc = %08X\n", rc);
193 exit(-1);
194 }
195
196 nsCOMPtr<nsIComponentManager> manager = do_QueryInterface(registrar);
197 if (!manager)
198 {
199 printf("Error: could not query nsIComponentManager interface!\n");
200 exit(-1);
201 }
202
203 nsCOMPtr<IVirtualBox> virtualBox;
204 rc = dcon->CreateInstanceByContractID(
205 serverID,
206 NS_VIRTUALBOX_CONTRACTID,
207 NS_GET_IID(IVirtualBox),
208 getter_AddRefs(virtualBox));
209 if (NS_FAILED(rc))
210 {
211 printf("Error, could not instantiate object! rc=0x%x\n", rc);
212 exit(-1);
213 }
214
215 nsCOMPtr<ISession> session;
216 rc = manager->CreateInstance((nsCID)NS_SESSION_CID,
217 nsnull,
218 NS_GET_IID(ISession),
219 getter_AddRefs(session));
220 if (NS_FAILED(rc))
221 {
222 printf("Error: could not instantiate Session object! rc = %08X\n", rc);
223 exit(-1);
224 }
225
226 // open session for this VM
227 rc = virtualBox->OpenSession(session, uuid);
228 if (NS_FAILED(rc))
229 {
230 printf("Error: given machine not found!\n");
231 exit(-1);
232 }
233 IMachine *machine = NULL;
234 session->GetMachine(&machine);
235 if (!machine)
236 {
237 printf("Error: given machine not found!\n");
238 exit(-1);
239 }
240 IConsole *console = NULL;
241 session->GetConsole(&console);
242 if (!console)
243 {
244 printf("Error: cannot get console!\n");
245 exit(-1);
246 }
247
248 IDisplay *display = NULL;
249 console->GetDisplay(&display);
250 if (!display)
251 {
252 printf("Error: could not get display object!\n");
253 exit(-1);
254 }
255
256 IKeyboard *keyboard = NULL;
257 IMouse *mouse = NULL;
258 VBoxDirectFB *frameBuffer = NULL;
259
260 /**
261 * Init DirectFB
262 */
263 IDirectFB *dfb = NULL;
264 IDirectFBSurface *surface = NULL;
265 IDirectFBInputDevice *dfbKeyboard = NULL;
266 IDirectFBInputDevice *dfbMouse = NULL;
267 IDirectFBEventBuffer *dfbEventBuffer = NULL;
268 DFBSurfaceDescription dsc;
269 int screen_width, screen_height;
270
271 DFBCHECK(DirectFBInit(&argc, &argv));
272 DFBCHECK(DirectFBCreate(&dfb));
273 DFBCHECK(dfb->SetCooperativeLevel(dfb, DFSCL_FULLSCREEN));
274 // populate our structure of supported video modes
275 DFBCHECK(dfb->EnumVideoModes(dfb, enumVideoModesHandler, NULL));
276
277 if (listHostModes)
278 {
279 printf("*****************************************************\n");
280 printf("Number of available host video modes: %u\n", numVideoModes);
281 for (uint32_t i = 0; i < numVideoModes; i++)
282 {
283 printf("Mode %u: xres = %u, yres = %u, bpp = %u\n", i,
284 videoModes[i].width, videoModes[i].height, videoModes[i].bpp);
285 }
286 printf("Note: display modes with bpp < have been filtered out\n");
287 printf("*****************************************************\n");
288 goto Leave;
289 }
290
291 if (useFixedVideoMode)
292 {
293 int32_t bestVideoMode = getBestVideoMode(fixedVideoMode.width,
294 fixedVideoMode.height,
295 fixedVideoMode.bpp);
296 // validate the fixed mode
297 if ((bestVideoMode == -1) ||
298 ((fixedVideoMode.width != videoModes[bestVideoMode].width) ||
299 (fixedVideoMode.height != videoModes[bestVideoMode].height) ||
300 (fixedVideoMode.bpp != videoModes[bestVideoMode].bpp)))
301 {
302 printf("Error: the specified fixed video mode is not available!\n");
303 exit(-1);
304 }
305 } else
306 {
307 initialVideoMode = getBestVideoMode(640, 480, 16);
308 if (initialVideoMode == -1)
309 {
310 printf("Error: initial video mode 640x480x16 is not available!\n");
311 exit(-1);
312 }
313 }
314
315 dsc.flags = DSDESC_CAPS;
316 dsc.caps = DSCAPS_PRIMARY;
317 DFBCHECK(dfb->CreateSurface(dfb, &dsc, &surface));
318 DFBCHECK(surface->Clear(surface, 0, 0, 0, 0));
319 DFBCHECK(surface->GetSize(surface, &screen_width, &screen_height));
320 DFBCHECK(dfb->GetInputDevice(dfb, DIDID_KEYBOARD, &dfbKeyboard));
321 DFBCHECK(dfbKeyboard->CreateEventBuffer(dfbKeyboard, &dfbEventBuffer));
322 DFBCHECK(dfb->GetInputDevice(dfb, DIDID_MOUSE, &dfbMouse));
323 DFBCHECK(dfbMouse->AttachEventBuffer(dfbMouse, dfbEventBuffer));
324
325
326 if (useFixedVideoMode)
327 {
328 printf("Information: setting video mode to %ux%ux%u\n", fixedVideoMode.width,
329 fixedVideoMode.height, fixedVideoMode.bpp);
330 DFBCHECK(dfb->SetVideoMode(dfb, fixedVideoMode.width,
331 fixedVideoMode.height, fixedVideoMode.bpp));
332 } else
333 {
334 printf("Information: starting with default video mode %ux%ux%u\n",
335 videoModes[initialVideoMode].width, videoModes[initialVideoMode].height,
336 videoModes[initialVideoMode].bpp);
337 DFBCHECK(dfb->SetVideoMode(dfb, videoModes[initialVideoMode].width,
338 videoModes[initialVideoMode].height,
339 videoModes[initialVideoMode].bpp));
340 }
341
342 // register our framebuffer
343 frameBuffer = new VBoxDirectFB(dfb, surface);
344 display->RegisterExternalFramebuffer(frameBuffer);
345
346 /**
347 * Start the VM execution thread
348 */
349 console->PowerUp(NULL);
350
351 console->GetKeyboard(&keyboard);
352 console->GetMouse(&mouse);
353
354 /**
355 * Main event loop
356 */
357 #define MAX_KEYEVENTS 10
358 int keyEvents[MAX_KEYEVENTS];
359 int numKeyEvents;
360
361 while (!quit)
362 {
363 DFBInputEvent event;
364
365 numKeyEvents = 0;
366 DFBCHECK(dfbEventBuffer->WaitForEvent(dfbEventBuffer));
367 while (dfbEventBuffer->GetEvent(dfbEventBuffer, DFB_EVENT(&event)) == DFB_OK)
368 {
369 int mouseXDelta = 0;
370 int mouseYDelta = 0;
371 int mouseZDelta = 0;
372 switch (event.type)
373 {
374 #define QUEUEEXT() keyEvents[numKeyEvents++] = 0xe0
375 #define QUEUEKEY(scan) keyEvents[numKeyEvents++] = scan | (event.type == DIET_KEYRELEASE ? 0x80 : 0x00)
376 #define QUEUEKEYRAW(scan) keyEvents[numKeyEvents++] = scan
377 case DIET_KEYPRESS:
378 case DIET_KEYRELEASE:
379 {
380 // @@@AH development hack to get out of it!
381 if ((event.key_id == DIKI_ESCAPE) && (event.modifiers & (DIMM_CONTROL | DIMM_ALT)))
382 quit = 1;
383
384 if (numKeyEvents < MAX_KEYEVENTS)
385 {
386 //printf("%s: key_code: 0x%x\n", event.type == DIET_KEYPRESS ? "DIET_KEYPRESS" : "DIET_KEYRELEASE", event.key_code);
387 switch ((uint32_t)event.key_id)
388 {
389 case DIKI_ALTGR:
390 QUEUEEXT();
391 QUEUEKEY(0x38);
392 break;
393 case DIKI_CONTROL_R:
394 QUEUEEXT();
395 QUEUEKEY(0x1d);
396 break;
397 case DIKI_INSERT:
398 QUEUEEXT();
399 QUEUEKEY(0x52);
400 break;
401 case DIKI_DELETE:
402 QUEUEEXT();
403 QUEUEKEY(0x53);
404 break;
405 case DIKI_HOME:
406 QUEUEEXT();
407 QUEUEKEY(0x47);
408 break;
409 case DIKI_END:
410 QUEUEEXT();
411 QUEUEKEY(0x4f);
412 break;
413 case DIKI_PAGE_UP:
414 QUEUEEXT();
415 QUEUEKEY(0x49);
416 break;
417 case DIKI_PAGE_DOWN:
418 QUEUEEXT();
419 QUEUEKEY(0x51);
420 break;
421 case DIKI_LEFT:
422 QUEUEEXT();
423 QUEUEKEY(0x4b);
424 break;
425 case DIKI_RIGHT:
426 QUEUEEXT();
427 QUEUEKEY(0x4d);
428 break;
429 case DIKI_UP:
430 QUEUEEXT();
431 QUEUEKEY(0x48);
432 break;
433 case DIKI_DOWN:
434 QUEUEEXT();
435 QUEUEKEY(0x50);
436 break;
437 case DIKI_KP_DIV:
438 QUEUEEXT();
439 QUEUEKEY(0x35);
440 break;
441 case DIKI_KP_ENTER:
442 QUEUEEXT();
443 QUEUEKEY(0x1c);
444 break;
445 case DIKI_PRINT:
446 // the break code is inverted!
447 if (event.type == DIET_KEYPRESS)
448 {
449 QUEUEEXT();
450 QUEUEKEY(0x2a);
451 QUEUEEXT();
452 QUEUEKEY(0x37);
453 } else
454 {
455 QUEUEEXT();
456 QUEUEKEY(0x37);
457 QUEUEEXT();
458 QUEUEKEY(0x2a);
459 }
460 break;
461 case DIKI_PAUSE:
462 // This is a super weird key. No break code and a 6 byte
463 // combination.
464 if (event.type == DIET_KEYPRESS)
465 {
466 QUEUEKEY(0xe1);
467 QUEUEKEY(0x1d);
468 QUEUEKEY(0x45);
469 QUEUEKEY(0xe1);
470 QUEUEKEY(0x9d);
471 QUEUEKEY(0xc5);
472 }
473 break;
474 case DIKI_META_L:
475 // the left Windows logo is a bit different
476 if (event.type == DIET_KEYPRESS)
477 {
478 QUEUEEXT();
479 QUEUEKEYRAW(0x1f);
480 } else
481 {
482 QUEUEEXT();
483 QUEUEKEYRAW(0xf0);
484 QUEUEKEYRAW(0x1f);
485 }
486 break;
487 case DIKI_META_R:
488 // the right Windows logo is a bit different
489 if (event.type == DIET_KEYPRESS)
490 {
491 QUEUEEXT();
492 QUEUEKEYRAW(0x27);
493 } else
494 {
495 QUEUEEXT();
496 QUEUEKEYRAW(0xf0);
497 QUEUEKEYRAW(0x27);
498 }
499 break;
500 case DIKI_SUPER_R:
501 // the popup menu is a bit different
502 if (event.type == DIET_KEYPRESS)
503 {
504 QUEUEEXT();
505 QUEUEKEYRAW(0x2f);
506 } else
507 {
508 QUEUEEXT();
509 QUEUEKEYRAW(0xf0);
510 QUEUEKEYRAW(0x2f);
511 }
512 break;
513
514 default:
515 // check if we got a hardware scancode
516 if (event.key_code != -1)
517 {
518 // take the scancode from DirectFB as is
519 QUEUEKEY(event.key_code);
520 } else
521 {
522 // XXX need extra handling!
523 }
524 }
525 }
526 break;
527 }
528 #undef QUEUEEXT
529 #undef QUEUEKEY
530 #undef QUEUEKEYRAW
531
532 case DIET_AXISMOTION:
533 {
534 switch (event.axis)
535 {
536 case DIAI_X:
537 mouseXDelta += event.axisrel;
538 break;
539 case DIAI_Y:
540 mouseYDelta += event.axisrel;
541 break;
542 case DIAI_Z:
543 mouseZDelta += event.axisrel;
544 break;
545 default:
546 break;
547 }
548 // fall through
549 }
550 case DIET_BUTTONPRESS:
551 // fall through;
552 case DIET_BUTTONRELEASE:
553 {
554 int buttonState = 0;
555 if (event.buttons & DIBM_LEFT)
556 buttonState |= MouseButtonState::LeftButton;
557 if (event.buttons & DIBM_RIGHT)
558 buttonState |= MouseButtonState::RightButton;
559 if (event.buttons & DIBM_MIDDLE)
560 buttonState |= MouseButtonState::MiddleButton;
561 mouse->PutMouseEvent(mouseXDelta, mouseYDelta, mouseZDelta,
562 buttonState);
563 break;
564 }
565 default:
566 break;
567 }
568 }
569 // did we get any keyboard events?
570 if (numKeyEvents > 0)
571 {
572 uint32_t codesStored;
573 if (numKeyEvents > 1)
574 {
575 com::SafeArray <LONG> keys (numKeyEvents);
576 for (size_t idx = 0; idx < keys.size(); ++idx)
577 keys[idx] = keyEvents[idx];
578 keyboard->PutScancodes(ComSafeArrayAsInParam(keys),
579 &codesStored);
580 } else
581 {
582 keyboard->PutScancode(keyEvents[0]);
583 }
584 }
585 }
586 console->PowerDown();
587Leave:
588 if (mouse)
589 mouse->Release();
590 if (keyboard)
591 keyboard->Release();
592 if (display)
593 display->Release();
594 if (console)
595 console->Release();
596 if (machine)
597 machine->Release();
598 virtualBox = NULL;
599
600 if (dfbEventBuffer)
601 dfbEventBuffer->Release(dfbEventBuffer);
602 if (dfbMouse)
603 dfbMouse->Release(dfbMouse);
604 if (dfbKeyboard)
605 dfbKeyboard->Release(dfbKeyboard);
606 if (surface)
607 surface->Release(surface);
608 if (dfb)
609 dfb->Release(dfb);
610
611 return 0;
612}
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette