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() }