commit a4a0941a039c37c64e3408575ac7c576975bd510 Author: Chakib Benziane Date: Fri Nov 16 23:51:05 2018 +0100 initial diff --git a/README.md b/README.md new file mode 100644 index 0000000..4a07403 --- /dev/null +++ b/README.md @@ -0,0 +1,2 @@ +# golang-ddcci-dll +Switching Monitor Source using DDC CI protocol with Golang and dxva2.dll diff --git a/tasker.go b/tasker.go new file mode 100755 index 0000000..e1ac1fe --- /dev/null +++ b/tasker.go @@ -0,0 +1,142 @@ +// Package main provides ... +package main + +import ( + "fmt" + "syscall" + "unsafe" + //"io/ioutil" + //"github.com/fvbock/endless" + "github.com/gin-gonic/gin" + //"log" + "net/http" + // "os" + // "os/exec" +) + +const ( + MOUSE_X = 1000 + MOUSE_Y = 1000 + M_POINT = ( MOUSE_X & 0xFFFFFFFF ) | ( MOUSE_Y << 32 ) + VPC_SOURCE_SELECT = '\x60' + WINDOWS_M = 15 + LINUX_M = 17 + + WINDOWS_PARAM = "windows" + LINUX_PARAM = "linux" +) + +var ( + user32, _ = syscall.LoadLibrary("User32.dll") + dxva2, _ = syscall.LoadLibrary("dxva2.dll") + monitorFromPoint, _ = syscall.GetProcAddress(user32, "MonitorFromPoint") + GetPhysicalMonitorsFromHMONITOR, _ = syscall.GetProcAddress(dxva2, "GetPhysicalMonitorsFromHMONITOR") + SetVCPFeature, _ = syscall.GetProcAddress(dxva2, "SetVCPFeature") + DestroyPhysicalMonitor, _ = syscall.GetProcAddress(dxva2, "DestroyPhysicalMonitor") +) + + func switchMonitorHandler(c *gin.Context) { + + os := c.Param("os") + + switch os { + case WINDOWS_PARAM: + go setMonitorInputSource(WINDOWS_M) + case LINUX_PARAM: + go setMonitorInputSource(LINUX_M) + } + + //fmt.Printf("Received command %s", command) + c.String(http.StatusOK, fmt.Sprintf("monitor switched to %s!", os)) +} + + +func getMonitorHandle() (result uintptr) { + var nargs uintptr = 2 + ret, _, callErr := syscall.Syscall( + uintptr(monitorFromPoint), + nargs, + uintptr(M_POINT), + uintptr(1), + 0) + + if callErr != 0 { + abort("Call getMonitorHandle", callErr) + } + + res := uintptr(ret) + result = getPhysicalMonitor(res) + return +} + +func getPhysicalMonitor(handle uintptr) (result uintptr) { + b := make([]byte, 256) + var nargs uintptr = 3 + _, _, callErr := syscall.Syscall( + uintptr(GetPhysicalMonitorsFromHMONITOR), + nargs, + handle, + uintptr(1), + uintptr(unsafe.Pointer(&b[0]))) + + if callErr != 0 { + abort("Call getPhysicalMonitor", callErr) + } + result = uintptr(b[0]) + return +} + +func setMonitorInputSource(source int) { + mHandle := getMonitorHandle() + + var nargs uintptr = 3 + _, _, callErr := syscall.Syscall( + uintptr(SetVCPFeature), + nargs, + uintptr(mHandle), + VPC_SOURCE_SELECT, + uintptr(source)) + + if callErr != 0 { + abort("Call SetVCPFeature", callErr) + } + destroyPhysicalMonitor(mHandle) +} + +func destroyPhysicalMonitor(monitor uintptr) { + var nargs uintptr = 1 + _, _, callErr := syscall.Syscall( + uintptr(DestroyPhysicalMonitor), + nargs, + monitor, + 0, + 0) + + if callErr != 0 { + abort("Call destroyPhysicalMonitor", callErr) + } +} + +func abort(funcname string, err error) { + panic(fmt.Sprintf("%s failed: %v", funcname, err)) +} + + + +func main() { + defer syscall.FreeLibrary(user32) + defer syscall.FreeLibrary(dxva2) + + router := gin.Default() + + router.Use(gin.Logger()) + router.Use(gin.Recovery()) + + monitor := router.Group("/monitor") + { + monitor.GET("/switch/:os", switchMonitorHandler) + } + + router.Run(":7500") + //endless.ListenAndServe(":7500", router) +}