VirtualBox

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

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

Main/Session+Console: By default, create a console with no sub-objects (saves resources). VM processes need to explicitly ask for a full console when before opening the session.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 22.4 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-2010 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/version.h>
30#include <VBox/param.h>
31#include <iprt/path.h>
32
33/**
34 * Globals
35 */
36uint32_t useFixedVideoMode = 0;
37int scaleGuest = 0;
38videoMode fixedVideoMode = {0};
39int32_t initialVideoMode = -1;
40
41void showusage()
42{
43 printf("\nThe following parameters are supported:\n"
44 "--startvm uuid start VM with UUID 'uuid'\n"
45 "--fixedres WxHxBPP always use fixed host resolution\n"
46 "--listhostmodes display list of suported host display modes and exit\n"
47 "--scale scale guest video mode to host video mode\n"
48 "--nodirectblit disable direct blitting, use intermediate framebuffer\n"
49 "--showlabel show VM name on top of the VM display\n");
50}
51
52/** entry point */
53int main(int argc, char *argv[])
54{
55 const char *uuid = NULL;
56 int c;
57 int listHostModes = 0;
58 int quit = 0;
59 const struct option options[] =
60 {
61 { "help", no_argument, NULL, 'h' },
62 { "startvm", required_argument, NULL, 's' },
63 { "fixedres", required_argument, NULL, 'f' },
64 { "listhostmodes", no_argument, NULL, 'l' },
65 { "scale", no_argument, NULL, 'c' }
66 };
67
68 printf("VirtualBox DirectFB GUI built %s %s\n"
69 "(C) 2004-2010 " VBOX_VENDOR "\n"
70 "(C) 2004-2005 secunet Security Networks AG\n", __DATE__, __TIME__);
71
72 for (;;)
73 {
74 c = getopt_long(argc, argv, "s:", options, NULL);
75 if (c == -1)
76 break;
77 switch (c)
78 {
79 case 'h':
80 {
81 showusage();
82 exit(0);
83 break;
84 }
85 case 's':
86 {
87 // UUID as string, parse it
88 RTUUID buuid;
89 if (!RT_SUCCESS(RTUuidFromStr((PRTUUID)&buuid, optarg)))
90 {
91 printf("Error, invalid UUID format given!\n");
92 showusage();
93 exit(-1);
94 }
95 uuid = optarg;
96 break;
97 }
98 case 'f':
99 {
100 if (sscanf(optarg, "%ux%ux%u", &fixedVideoMode.width, &fixedVideoMode.height,
101 &fixedVideoMode.bpp) != 3)
102 {
103 printf("Error, invalid resolution argument!\n");
104 showusage();
105 exit(-1);
106 }
107 useFixedVideoMode = 1;
108 break;
109 }
110 case 'l':
111 {
112 listHostModes = 1;
113 break;
114 }
115 case 'c':
116 {
117 scaleGuest = 1;
118 break;
119 }
120 default:
121 break;
122 }
123 }
124
125 // check if we got a UUID
126 if (!uuid)
127 {
128 printf("Error, no UUID given!\n");
129 showusage();
130 exit(-1);
131 }
132
133
134 /**
135 * XPCOM setup
136 */
137
138 nsresult rc;
139 /*
140 * Note that we scope all nsCOMPtr variables in order to have all XPCOM
141 * objects automatically released before we call NS_ShutdownXPCOM at the
142 * end. This is an XPCOM requirement.
143 */
144 {
145 nsCOMPtr<nsIServiceManager> serviceManager;
146 rc = NS_InitXPCOM2(getter_AddRefs(serviceManager), nsnull, nsnull);
147 if (NS_FAILED(rc))
148 {
149 printf("Error: XPCOM could not be initialized! rc=0x%x\n", rc);
150 exit(-1);
151 }
152
153 // register our component
154 nsCOMPtr<nsIComponentRegistrar> registrar = do_QueryInterface(serviceManager);
155 if (!registrar)
156 {
157 printf("Error: could not query nsIComponentRegistrar interface!\n");
158 exit(-1);
159 }
160 registrar->AutoRegister(nsnull);
161
162 /*
163 * Make sure the main event queue is created. This event queue is
164 * responsible for dispatching incoming XPCOM IPC messages. The main
165 * thread should run this event queue's loop during lengthy non-XPCOM
166 * operations to ensure messages from the VirtualBox server and other
167 * XPCOM IPC clients are processed. This use case doesn't perform such
168 * operations so it doesn't run the event loop.
169 */
170 nsCOMPtr<nsIEventQueue> eventQ;
171 rc = NS_GetMainEventQ(getter_AddRefs (eventQ));
172 if (NS_FAILED(rc))
173 {
174 printf("Error: could not get main event queue! rc=%08X\n", rc);
175 return -1;
176 }
177
178 /*
179 * Now XPCOM is ready and we can start to do real work.
180 * IVirtualBox is the root interface of VirtualBox and will be
181 * retrieved from the XPCOM component manager. We use the
182 * XPCOM provided smart pointer nsCOMPtr for all objects because
183 * that's very convenient and removes the need deal with reference
184 * counting and freeing.
185 */
186 nsCOMPtr<nsIComponentManager> manager;
187 rc = NS_GetComponentManager (getter_AddRefs (manager));
188 if (NS_FAILED(rc))
189 {
190 printf("Error: could not get component manager! rc=%08X\n", rc);
191 exit(-1);
192 }
193
194 nsCOMPtr<IVirtualBox> virtualBox;
195 rc = manager->CreateInstanceByContractID(NS_VIRTUALBOX_CONTRACTID,
196 nsnull,
197 NS_GET_IID(IVirtualBox),
198 getter_AddRefs(virtualBox));
199 if (NS_FAILED(rc))
200 {
201 printf("Error, could not instantiate object! rc=0x%x\n", rc);
202 exit(-1);
203 }
204
205 nsCOMPtr<ISession> session;
206 rc = manager->CreateInstance(CLSID_Session,
207 nsnull,
208 NS_GET_IID(ISession),
209 getter_AddRefs(session));
210 if (NS_FAILED(rc))
211 {
212 printf("Error: could not instantiate Session object! rc = %08X\n", rc);
213 exit(-1);
214 }
215
216 rc = session->SetFullConsole(true);
217 if (NS_FAILED(rc))
218 {
219 printf("Error: could not select full VM console! rc = %08X\n", rc);
220 exit(-1);
221 }
222
223 // open session for this VM
224 rc = virtualBox->OpenSession(session, NS_ConvertUTF8toUTF16(uuid).get());
225 if (NS_FAILED(rc))
226 {
227 printf("Error: given machine not found!\n");
228 exit(-1);
229 }
230 nsCOMPtr<IMachine> machine;
231 session->GetMachine(getter_AddRefs(machine));
232 if (!machine)
233 {
234 printf("Error: given machine not found!\n");
235 exit(-1);
236 }
237 nsCOMPtr<IConsole> console;
238 session->GetConsole(getter_AddRefs(console));
239 if (!console)
240 {
241 printf("Error: cannot get console!\n");
242 exit(-1);
243 }
244
245 nsCOMPtr<IDisplay> display;
246 console->GetDisplay(getter_AddRefs(display));
247 if (!display)
248 {
249 printf("Error: could not get display object!\n");
250 exit(-1);
251 }
252
253 nsCOMPtr<IKeyboard> keyboard;
254 nsCOMPtr<IMouse> mouse;
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->SetFramebuffer(0, frameBuffer);
342
343 /**
344 * Start the VM execution thread
345 */
346 console->PowerUp(NULL);
347
348 console->GetKeyboard(getter_AddRefs(keyboard));
349 console->GetMouse(getter_AddRefs(mouse));
350
351 /**
352 * Main event loop
353 */
354 #define MAX_KEYEVENTS 10
355 PRInt32 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_CONTROL_R:
387 QUEUEEXT();
388 QUEUEKEY(0x1d);
389 break;
390 case DIKI_INSERT:
391 QUEUEEXT();
392 QUEUEKEY(0x52);
393 break;
394 case DIKI_DELETE:
395 QUEUEEXT();
396 QUEUEKEY(0x53);
397 break;
398 case DIKI_HOME:
399 QUEUEEXT();
400 QUEUEKEY(0x47);
401 break;
402 case DIKI_END:
403 QUEUEEXT();
404 QUEUEKEY(0x4f);
405 break;
406 case DIKI_PAGE_UP:
407 QUEUEEXT();
408 QUEUEKEY(0x49);
409 break;
410 case DIKI_PAGE_DOWN:
411 QUEUEEXT();
412 QUEUEKEY(0x51);
413 break;
414 case DIKI_LEFT:
415 QUEUEEXT();
416 QUEUEKEY(0x4b);
417 break;
418 case DIKI_RIGHT:
419 QUEUEEXT();
420 QUEUEKEY(0x4d);
421 break;
422 case DIKI_UP:
423 QUEUEEXT();
424 QUEUEKEY(0x48);
425 break;
426 case DIKI_DOWN:
427 QUEUEEXT();
428 QUEUEKEY(0x50);
429 break;
430 case DIKI_KP_DIV:
431 QUEUEEXT();
432 QUEUEKEY(0x35);
433 break;
434 case DIKI_KP_ENTER:
435 QUEUEEXT();
436 QUEUEKEY(0x1c);
437 break;
438 case DIKI_PRINT:
439 // the break code is inverted!
440 if (event.type == DIET_KEYPRESS)
441 {
442 QUEUEEXT();
443 QUEUEKEY(0x2a);
444 QUEUEEXT();
445 QUEUEKEY(0x37);
446 } else
447 {
448 QUEUEEXT();
449 QUEUEKEY(0x37);
450 QUEUEEXT();
451 QUEUEKEY(0x2a);
452 }
453 break;
454 case DIKI_PAUSE:
455 // This is a super weird key. No break code and a 6 byte
456 // combination.
457 if (event.type == DIET_KEYPRESS)
458 {
459 QUEUEKEY(0xe1);
460 QUEUEKEY(0x1d);
461 QUEUEKEY(0x45);
462 QUEUEKEY(0xe1);
463 QUEUEKEY(0x9d);
464 QUEUEKEY(0xc5);
465 }
466 break;
467 case DIKI_META_L:
468 // the left Windows logo is a bit different
469 if (event.type == DIET_KEYPRESS)
470 {
471 QUEUEEXT();
472 QUEUEKEYRAW(0x1f);
473 } else
474 {
475 QUEUEEXT();
476 QUEUEKEYRAW(0xf0);
477 QUEUEKEYRAW(0x1f);
478 }
479 break;
480 case DIKI_META_R:
481 // the right Windows logo is a bit different
482 if (event.type == DIET_KEYPRESS)
483 {
484 QUEUEEXT();
485 QUEUEKEYRAW(0x27);
486 } else
487 {
488 QUEUEEXT();
489 QUEUEKEYRAW(0xf0);
490 QUEUEKEYRAW(0x27);
491 }
492 break;
493 case DIKI_SUPER_R:
494 // the popup menu is a bit different
495 if (event.type == DIET_KEYPRESS)
496 {
497 QUEUEEXT();
498 QUEUEKEYRAW(0x2f);
499 } else
500 {
501 QUEUEEXT();
502 QUEUEKEYRAW(0xf0);
503 QUEUEKEYRAW(0x2f);
504 }
505 break;
506
507 default:
508 // check if we got a hardware scancode
509 if (event.key_code != -1)
510 {
511 // take the scancode from DirectFB as is
512 QUEUEKEY(event.key_code);
513 } else
514 {
515 // XXX need extra handling!
516 }
517 }
518 }
519 break;
520 }
521 #undef QUEUEEXT
522 #undef QUEUEKEY
523 #undef QUEUEKEYRAW
524
525 case DIET_AXISMOTION:
526 {
527 switch (event.axis)
528 {
529 case DIAI_X:
530 mouseXDelta += event.axisrel;
531 break;
532 case DIAI_Y:
533 mouseYDelta += event.axisrel;
534 break;
535 case DIAI_Z:
536 mouseZDelta += event.axisrel;
537 break;
538 default:
539 break;
540 }
541 // fall through
542 }
543 case DIET_BUTTONPRESS:
544 // fall through;
545 case DIET_BUTTONRELEASE:
546 {
547 int buttonState = 0;
548 if (event.buttons & DIBM_LEFT)
549 buttonState |= MouseButtonState::LeftButton;
550 if (event.buttons & DIBM_RIGHT)
551 buttonState |= MouseButtonState::RightButton;
552 if (event.buttons & DIBM_MIDDLE)
553 buttonState |= MouseButtonState::MiddleButton;
554 mouse->PutMouseEvent(mouseXDelta, mouseYDelta, mouseZDelta,
555 0, buttonState);
556 break;
557 }
558 default:
559 break;
560 }
561 }
562 // did we get any keyboard events?
563 if (numKeyEvents > 0)
564 {
565 uint32_t codesStored;
566 if (numKeyEvents > 1)
567 {
568 keyboard->PutScancodes(numKeyEvents, keyEvents,
569 &codesStored);
570 } else
571 {
572 keyboard->PutScancode(keyEvents[0]);
573 }
574 }
575 }
576 {
577 nsCOMPtr<IProgress> progress;
578 console->PowerDown(getter_AddRefs(progress));
579 progress->WaitForCompletion(-1);
580 }
581 }
582
583Leave:
584 /*
585 * Perform the standard XPCOM shutdown procedure.
586 */
587 NS_ShutdownXPCOM(nsnull);
588
589 return 0;
590}
Note: See TracBrowser for help on using the repository browser.

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