VirtualBox

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

Last change on this file since 8132 was 8132, checked in by vboxsync, 17 years ago

more rebranding

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