VirtualBox

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

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

(C) 2008

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