VirtualBox

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

Last change on this file since 26600 was 26089, checked in by vboxsync, 15 years ago

Branding: Moved the Product & Vendor strings to kBuild, so it could be used
there as well. Added a Copyright year define which points to the current year.
All this should be used on more places. For now the help strings of the
Frontends and most strings of the Mac OS X installer are updated.

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