func (vb *VirtualBox) Init() error { if C.VBoxCGlueInit() != 0 { message := fmt.Sprintf("VBoxCGlueInit failed: %v", C.g_szVBoxErrMsg) log.Println(message) return errors.New(message) } //unsigned ver = g_pVBoxFuncs->pfnGetVersion(); //printf("VirtualBox version: %u.%u.%u\n", ver / 1000000, ver / 1000 % 1000, ver % 1000); //ver = g_pVBoxFuncs->pfnGetAPIVersion(); //printf("VirtualBox API version: %u.%u\n", ver / 1000, ver % 1000); C.ClientInitialize(&vb.vboxclient) if vb.vboxclient == nil { message := fmt.Sprintf("Could not get vboxclient reference") log.Println(message) return errors.New(message) } var rc C.HRESULT = C.GetVirtualBox(vb.vboxclient, &vb.vbox) if C.MY_FAILED(rc) != 0 || vb.vbox == nil { message := fmt.Sprintf("Could not get vbox reference") log.Println(message) return errors.New(message) } rc = C.GetSession(vb.vboxclient, &vb.session) if C.MY_FAILED(rc) != 0 || vb.session == nil { message := fmt.Sprintf("Could not get session reference") log.Println(message) return errors.New(message) } return nil }
func (vm *VirtualMachine) GetScreenshot() (*image.NRGBA, error) { if !vm.locked { message := fmt.Sprintf("Machine not locked, can't take screenshot") log.Println(message) return nil, errors.New(message) } width := C.uint(0) height := C.uint(0) bitsPerPixel := C.uint(0) //TODO: is vm.Display threadsafe? var rc C.HRESULT = C.GetScreenResolution(vm.Display, &width, &height, &bitsPerPixel) if C.MY_FAILED(rc) != 0 { message := fmt.Sprintf("Failed to get screen resolution") log.Println(message) return nil, errors.New(message) } //var imageData [int(width)*(height)*4]char var imageDataSize C.PRUint32 var imageData *C.PRUint8 defer C.free(unsafe.Pointer(imageData)) rc = C.TakeScreenShotPNGToArray(vm.Display, width, height, &imageDataSize, &imageData) if C.MY_FAILED(rc) != 0 { message := fmt.Sprintf("Failed to get screen shot data") log.Println(message) return nil, errors.New(message) } // convert data to a go byte array dataSize := int(imageDataSize) dataBytes := C.GoBytes(unsafe.Pointer(imageData), C.int(dataSize)) reader := bytes.NewReader(dataBytes) imgUnknown, err := png.Decode(reader) //this guy is probably RGBA if err != nil { message := fmt.Sprintf("Failed to decode image from png raw data", err) log.Println(message) return nil, err } // copy the image into NRGBA format. This is wasteful (TODO?) b := imgUnknown.Bounds() imgNRGBA := image.NewNRGBA(image.Rect(0, 0, b.Dx(), b.Dy())) draw.Draw(imgNRGBA, imgNRGBA.Bounds(), imgUnknown, b.Min, draw.Src) return imgNRGBA, nil }
// I guess this one expects the vm to be active already, the other possibility would be "LaunchVMProcess" func (vm *VirtualMachine) LockMachine() error { var rc C.HRESULT = C.LockMachine(vm.Machine, vm.Session) if C.MY_FAILED(rc) != 0 { vm.locked = false message := fmt.Sprintf("Could not lock machine") log.Println(message) return errors.New(message) } vm.locked = true rc = C.GetConsole(vm.Session, &vm.Console) if C.MY_FAILED(rc) != 0 || vm.Console == nil { vm.UnlockMachine() message := fmt.Sprintf("Could not get console reference") log.Println(message) return errors.New(message) } rc = C.GetMouse(vm.Console, &vm.Mouse) if C.MY_FAILED(rc) != 0 || vm.Mouse == nil { vm.UnlockMachine() message := fmt.Sprintf("Could not get mouse reference") log.Println(message) return errors.New(message) } rc = C.GetKeyboard(vm.Console, &vm.Keyboard) if C.MY_FAILED(rc) != 0 || vm.Keyboard == nil { vm.UnlockMachine() message := fmt.Sprintf("Could not get keyboard reference") log.Println(message) return errors.New(message) } rc = C.GetDisplay(vm.Console, &vm.Display) if C.MY_FAILED(rc) != 0 || vm.Display == nil { vm.UnlockMachine() message := fmt.Sprintf("Could not get display reference") log.Println(message) return errors.New(message) } return nil }
func (vm *VirtualMachine) UnlockMachine() error { var rc C.HRESULT = C.UnlockMachine(vm.Session) if C.MY_FAILED(rc) != 0 { message := fmt.Sprintf("Could not unlock machine") log.Println(message) return errors.New(message) } vm.locked = false return nil }
//state should be one of MOUSE_EVENT_... func (vm *VirtualMachine) MouseEvent(x, y, state int) error { if !vm.locked { message := fmt.Sprintf("Machine not locked, can't perform mouse down") log.Println(message) return errors.New(message) } var rc C.HRESULT = C.MouseClickEvent(vm.Mouse, C.int(x), C.int(y), C.int(state)) if C.MY_FAILED(rc) != 0 { message := fmt.Sprintf("Failed to perform mouse down") log.Println(message) return errors.New(message) } return nil }
// TODO: name is actually nameOrId func (vb *VirtualBox) ConnectToMachine(name string) (*VirtualMachine, error) { var machine *C.IMachine cs := C.CString(name) defer C.free(unsafe.Pointer(cs)) var rc C.HRESULT = C.FindMachine(vb.vbox, cs, &machine) if C.MY_FAILED(rc) != 0 || machine == nil { if machine != nil { defer C.free(unsafe.Pointer(machine)) } message := fmt.Sprintf("Could not get machine reference") log.Println(message) return nil, errors.New(message) } vm := new(VirtualMachine) vm.Machine = machine vm.Name = name vm.Session = vb.session vm.locked = false return vm, nil }