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