mirror of https://github.com/jetkvm/kvm.git
277 lines
6.7 KiB
Go
277 lines
6.7 KiB
Go
//go:build linux
|
|
|
|
package native
|
|
|
|
import (
|
|
"fmt"
|
|
"unsafe"
|
|
|
|
"github.com/rs/zerolog"
|
|
)
|
|
|
|
/*
|
|
#cgo LDFLAGS: -Llib -ljknative -llvgl
|
|
#cgo CFLAGS: -Iinclude
|
|
#include "ctrl.h"
|
|
#include <stdlib.h>
|
|
|
|
typedef const char cchar_t;
|
|
typedef const uint8_t cuint8_t;
|
|
|
|
extern void jetkvm_go_log_handler(int level, cchar_t *filename, cchar_t *funcname, int line, cchar_t *message);
|
|
static inline void jetkvm_cgo_setup_log_handler() {
|
|
jetkvm_set_log_handler(&jetkvm_go_log_handler);
|
|
}
|
|
|
|
extern void jetkvm_go_video_state_handler(jetkvm_video_state_t *state);
|
|
static inline void jetkvm_cgo_setup_video_state_handler() {
|
|
jetkvm_set_video_state_handler(&jetkvm_go_video_state_handler);
|
|
}
|
|
|
|
extern void jetkvm_go_video_handler(cuint8_t *frame, ssize_t len);
|
|
static inline void jetkvm_cgo_setup_video_handler() {
|
|
jetkvm_set_video_handler(&jetkvm_go_video_handler);
|
|
}
|
|
|
|
extern void jetkvm_go_indev_handler(int code);
|
|
static inline void jetkvm_cgo_setup_indev_handler() {
|
|
jetkvm_set_indev_handler(&jetkvm_go_indev_handler);
|
|
}
|
|
*/
|
|
import "C"
|
|
|
|
//export jetkvm_go_video_state_handler
|
|
func jetkvm_go_video_state_handler(state *C.jetkvm_video_state_t) {
|
|
videoState := VideoState{
|
|
Ready: bool(state.ready),
|
|
Error: C.GoString(state.error),
|
|
Width: int(state.width),
|
|
Height: int(state.height),
|
|
FramePerSecond: float64(state.frame_per_second),
|
|
}
|
|
videoStateChan <- videoState
|
|
}
|
|
|
|
//export jetkvm_go_log_handler
|
|
func jetkvm_go_log_handler(level C.int, filename *C.cchar_t, funcname *C.cchar_t, line C.int, message *C.cchar_t) {
|
|
logMessage := nativeLogMessage{
|
|
Level: zerolog.Level(level),
|
|
Message: C.GoString(message),
|
|
File: C.GoString(filename),
|
|
FuncName: C.GoString(funcname),
|
|
Line: int(line),
|
|
}
|
|
|
|
logChan <- logMessage
|
|
}
|
|
|
|
//export jetkvm_go_video_handler
|
|
func jetkvm_go_video_handler(frame *C.cuint8_t, len C.ssize_t) {
|
|
videoFrameChan <- C.GoBytes(unsafe.Pointer(frame), C.int(len))
|
|
}
|
|
|
|
//export jetkvm_go_indev_handler
|
|
func jetkvm_go_indev_handler(code C.int) {
|
|
indevEventChan <- int(code)
|
|
}
|
|
|
|
var eventCodeToNameMap = map[int]string{}
|
|
|
|
func uiEventCodeToName(code int) string {
|
|
name, ok := eventCodeToNameMap[code]
|
|
if !ok {
|
|
cCode := C.int(code)
|
|
cName := C.jetkvm_ui_event_code_to_name(cCode)
|
|
name = C.GoString(cName)
|
|
eventCodeToNameMap[code] = name
|
|
}
|
|
|
|
return name
|
|
}
|
|
|
|
func setUpNativeHandlers() {
|
|
C.jetkvm_cgo_setup_log_handler()
|
|
C.jetkvm_cgo_setup_video_state_handler()
|
|
C.jetkvm_cgo_setup_video_handler()
|
|
C.jetkvm_cgo_setup_indev_handler()
|
|
}
|
|
|
|
func uiInit(rotation uint16) {
|
|
cRotation := C.u_int16_t(rotation)
|
|
defer C.free(unsafe.Pointer(&cRotation))
|
|
|
|
C.jetkvm_ui_init(cRotation)
|
|
}
|
|
|
|
func uiTick() {
|
|
C.jetkvm_ui_tick()
|
|
}
|
|
|
|
func videoInit() error {
|
|
ret := C.jetkvm_video_init()
|
|
if ret != 0 {
|
|
return fmt.Errorf("failed to initialize video: %d", ret)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func videoShutdown() {
|
|
C.jetkvm_video_shutdown()
|
|
}
|
|
|
|
func videoStart() {
|
|
C.jetkvm_video_start()
|
|
}
|
|
|
|
func videoStop() {
|
|
C.jetkvm_video_stop()
|
|
}
|
|
|
|
func uiSetVar(name string, value string) {
|
|
nameCStr := C.CString(name)
|
|
defer C.free(unsafe.Pointer(nameCStr))
|
|
|
|
valueCStr := C.CString(value)
|
|
defer C.free(unsafe.Pointer(valueCStr))
|
|
|
|
C.jetkvm_ui_set_var(nameCStr, valueCStr)
|
|
}
|
|
|
|
func uiGetVar(name string) string {
|
|
nameCStr := C.CString(name)
|
|
defer C.free(unsafe.Pointer(nameCStr))
|
|
|
|
return C.GoString(C.jetkvm_ui_get_var(nameCStr))
|
|
}
|
|
|
|
func uiSwitchToScreen(screen string) {
|
|
screenCStr := C.CString(screen)
|
|
defer C.free(unsafe.Pointer(screenCStr))
|
|
C.jetkvm_ui_load_screen(screenCStr)
|
|
}
|
|
|
|
func uiGetCurrentScreen() string {
|
|
screenCStr := C.jetkvm_ui_get_current_screen()
|
|
return C.GoString(screenCStr)
|
|
}
|
|
|
|
func uiObjSetState(objName string, state string) (bool, error) {
|
|
objNameCStr := C.CString(objName)
|
|
defer C.free(unsafe.Pointer(objNameCStr))
|
|
stateCStr := C.CString(state)
|
|
defer C.free(unsafe.Pointer(stateCStr))
|
|
C.jetkvm_ui_set_state(objNameCStr, stateCStr)
|
|
return true, nil
|
|
}
|
|
|
|
// TODO: use Enum instead of string but it's not a hot path and performance is not a concern now
|
|
func uiObjAddFlag(objName string, flag string) (bool, error) {
|
|
objNameCStr := C.CString(objName)
|
|
defer C.free(unsafe.Pointer(objNameCStr))
|
|
flagCStr := C.CString(flag)
|
|
defer C.free(unsafe.Pointer(flagCStr))
|
|
C.jetkvm_ui_add_flag(objNameCStr, flagCStr)
|
|
return true, nil
|
|
}
|
|
|
|
func uiObjClearFlag(objName string, flag string) (bool, error) {
|
|
objNameCStr := C.CString(objName)
|
|
defer C.free(unsafe.Pointer(objNameCStr))
|
|
flagCStr := C.CString(flag)
|
|
defer C.free(unsafe.Pointer(flagCStr))
|
|
C.jetkvm_ui_clear_flag(objNameCStr, flagCStr)
|
|
return true, nil
|
|
}
|
|
|
|
func uiObjHide(objName string) (bool, error) {
|
|
return uiObjAddFlag(objName, "LV_OBJ_FLAG_HIDDEN")
|
|
}
|
|
|
|
func uiObjShow(objName string) (bool, error) {
|
|
return uiObjClearFlag(objName, "LV_OBJ_FLAG_HIDDEN")
|
|
}
|
|
|
|
func uiObjSetOpacity(objName string, opacity int) (bool, error) {
|
|
objNameCStr := C.CString(objName)
|
|
defer C.free(unsafe.Pointer(objNameCStr))
|
|
|
|
C.jetkvm_ui_set_opacity(objNameCStr, C.u_int8_t(opacity))
|
|
return true, nil
|
|
}
|
|
|
|
func uiObjFadeIn(objName string, duration uint32) (bool, error) {
|
|
objNameCStr := C.CString(objName)
|
|
defer C.free(unsafe.Pointer(objNameCStr))
|
|
|
|
C.jetkvm_ui_fade_in(objNameCStr, C.u_int32_t(duration))
|
|
|
|
return true, nil
|
|
}
|
|
|
|
func uiObjFadeOut(objName string, duration uint32) (bool, error) {
|
|
objNameCStr := C.CString(objName)
|
|
defer C.free(unsafe.Pointer(objNameCStr))
|
|
|
|
C.jetkvm_ui_fade_out(objNameCStr, C.u_int32_t(duration))
|
|
|
|
return true, nil
|
|
}
|
|
|
|
func uiLabelSetText(objName string, text string) (bool, error) {
|
|
objNameCStr := C.CString(objName)
|
|
defer C.free(unsafe.Pointer(objNameCStr))
|
|
|
|
textCStr := C.CString(text)
|
|
defer C.free(unsafe.Pointer(textCStr))
|
|
|
|
ret := C.jetkvm_ui_set_text(objNameCStr, textCStr)
|
|
if ret < 0 {
|
|
return false, fmt.Errorf("failed to set text: %d", ret)
|
|
}
|
|
return ret == 0, nil
|
|
}
|
|
|
|
func uiImgSetSrc(objName string, src string) (bool, error) {
|
|
objNameCStr := C.CString(objName)
|
|
defer C.free(unsafe.Pointer(objNameCStr))
|
|
|
|
srcCStr := C.CString(src)
|
|
defer C.free(unsafe.Pointer(srcCStr))
|
|
|
|
C.jetkvm_ui_set_image(objNameCStr, srcCStr)
|
|
|
|
return true, nil
|
|
}
|
|
|
|
func uiDispSetRotation(rotation uint16) (bool, error) {
|
|
nativeLogger.Info().Uint16("rotation", rotation).Msg("setting rotation")
|
|
|
|
cRotation := C.u_int16_t(rotation)
|
|
defer C.free(unsafe.Pointer(&cRotation))
|
|
|
|
C.jetkvm_ui_set_rotation(cRotation)
|
|
return true, nil
|
|
}
|
|
|
|
func videoGetStreamQualityFactor() (float64, error) {
|
|
factor := C.jetkvm_video_get_quality_factor()
|
|
return float64(factor), nil
|
|
}
|
|
|
|
func videoSetStreamQualityFactor(factor float64) error {
|
|
C.jetkvm_video_set_quality_factor(C.float(factor))
|
|
return nil
|
|
}
|
|
|
|
func videoGetEDID() (string, error) {
|
|
edidCStr := C.jetkvm_video_get_edid_hex()
|
|
return C.GoString(edidCStr), nil
|
|
}
|
|
|
|
func videoSetEDID(edid string) error {
|
|
edidCStr := C.CString(edid)
|
|
defer C.free(unsafe.Pointer(edidCStr))
|
|
C.jetkvm_video_set_edid(edidCStr)
|
|
return nil
|
|
}
|