initial
commit
a4a0941a03
@ -0,0 +1,2 @@
|
|||||||
|
# golang-ddcci-dll
|
||||||
|
Switching Monitor Source using DDC CI protocol with Golang and dxva2.dll
|
@ -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)
|
||||||
|
}
|
Loading…
Reference in New Issue