kvm/internal/native/native.go

119 lines
3.0 KiB
Go

package native
import (
"sync"
"time"
"github.com/Masterminds/semver/v3"
"github.com/rs/zerolog"
)
type Native struct {
ready chan struct{}
l *zerolog.Logger
lD *zerolog.Logger
systemVersion *semver.Version
appVersion *semver.Version
displayRotation uint16
onVideoStateChange func(state VideoState)
onVideoFrameReceived func(frame []byte, duration time.Duration)
onIndevEvent func(event string)
onRpcEvent func(event string)
videoLock sync.Mutex
screenLock sync.Mutex
}
type NativeOptions struct {
SystemVersion *semver.Version
AppVersion *semver.Version
DisplayRotation uint16
OnVideoStateChange func(state VideoState)
OnVideoFrameReceived func(frame []byte, duration time.Duration)
OnIndevEvent func(event string)
OnRpcEvent func(event string)
}
func NewNative(opts NativeOptions) *Native {
onVideoStateChange := opts.OnVideoStateChange
if onVideoStateChange == nil {
onVideoStateChange = func(state VideoState) {
nativeLogger.Info().Interface("state", state).Msg("video state changed")
}
}
onVideoFrameReceived := opts.OnVideoFrameReceived
if onVideoFrameReceived == nil {
onVideoFrameReceived = func(frame []byte, duration time.Duration) {
nativeLogger.Info().Interface("frame", frame).Dur("duration", duration).Msg("video frame received")
}
}
onIndevEvent := opts.OnIndevEvent
if onIndevEvent == nil {
onIndevEvent = func(event string) {
nativeLogger.Info().Str("event", event).Msg("indev event")
}
}
onRpcEvent := opts.OnRpcEvent
if onRpcEvent == nil {
onRpcEvent = func(event string) {
nativeLogger.Info().Str("event", event).Msg("rpc event")
}
}
return &Native{
ready: make(chan struct{}),
l: nativeLogger,
lD: displayLogger,
systemVersion: opts.SystemVersion,
appVersion: opts.AppVersion,
displayRotation: opts.DisplayRotation,
onVideoStateChange: onVideoStateChange,
onVideoFrameReceived: onVideoFrameReceived,
onIndevEvent: onIndevEvent,
onRpcEvent: onRpcEvent,
videoLock: sync.Mutex{},
screenLock: sync.Mutex{},
}
}
func (n *Native) Start() {
// set up singleton
setInstance(n)
setUpNativeHandlers()
// start the native video
go n.handleLogChan()
go n.handleVideoStateChan()
go n.handleVideoFrameChan()
go n.handleIndevEventChan()
go n.handleRpcEventChan()
n.initUI()
go n.tickUI()
if err := videoInit(); err != nil {
n.l.Error().Err(err).Msg("failed to initialize video")
}
close(n.ready)
}
// DoNotUseThisIsForCrashTestingOnly
// will crash the program in cgo code
func (n *Native) DoNotUseThisIsForCrashTestingOnly() {
defer func() {
if r := recover(); r != nil {
n.l.Error().Msg("recovered from crash")
}
}()
crash()
}
// GetLVGLVersion returns the LVGL version
func GetLVGLVersion() string {
return uiGetLVGLVersion()
}