VirtualBox

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

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

back out Main/Session+Console hack introducing full/reduced console

  • 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-2010 " 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