kvm/internal/native/native.go

162 lines
4.2 KiB
Go

package native
import (
"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
onVideoStateChange func(state VideoState)
onVideoFrameReceived func(frame []byte, duration time.Duration)
}
type NativeOptions struct {
SystemVersion *semver.Version
AppVersion *semver.Version
OnVideoStateChange func(state VideoState)
OnVideoFrameReceived func(frame []byte, duration time.Duration)
}
func NewNative(opts NativeOptions) *Native {
onVideoStateChange := opts.OnVideoStateChange
if onVideoStateChange == nil {
onVideoStateChange = func(state VideoState) {
nativeLogger.Info().Msg("video state changed")
}
}
onVideoFrameReceived := opts.OnVideoFrameReceived
if onVideoFrameReceived == nil {
onVideoFrameReceived = func(frame []byte, duration time.Duration) {
nativeLogger.Info().Msg("video frame received")
}
}
return &Native{
ready: make(chan struct{}),
l: nativeLogger,
lD: displayLogger,
systemVersion: opts.SystemVersion,
appVersion: opts.AppVersion,
onVideoStateChange: opts.OnVideoStateChange,
onVideoFrameReceived: opts.OnVideoFrameReceived,
}
}
func (n *Native) Start() {
go n.StartNativeVideo()
go n.HandleVideoChan()
}
func (n *Native) HandleVideoChan() {
lastFrame := time.Now()
for {
frame := <-jkVideoChan
now := time.Now()
sinceLastFrame := now.Sub(lastFrame)
lastFrame = now
n.onVideoFrameReceived(frame, sinceLastFrame)
}
}
// func handleCtrlClient(conn net.Conn) {
// defer conn.Close()
// scopedLogger := nativeLogger.With().
// Str("addr", conn.RemoteAddr().String()).
// Str("type", "ctrl").
// Logger()
// scopedLogger.Info().Msg("native ctrl socket client connected")
// if ctrlSocketConn != nil {
// scopedLogger.Debug().Msg("closing existing native socket connection")
// ctrlSocketConn.Close()
// }
// ctrlSocketConn = conn
// // Restore HDMI EDID if applicable
// go restoreHdmiEdid()
// readBuf := make([]byte, 4096)
// for {
// n, err := conn.Read(readBuf)
// if err != nil {
// scopedLogger.Warn().Err(err).Msg("error reading from ctrl sock")
// break
// }
// readMsg := string(readBuf[:n])
// ctrlResp := CtrlResponse{}
// err = json.Unmarshal([]byte(readMsg), &ctrlResp)
// if err != nil {
// scopedLogger.Warn().Err(err).Str("data", readMsg).Msg("error parsing ctrl sock msg")
// continue
// }
// scopedLogger.Trace().Interface("data", ctrlResp).Msg("ctrl sock msg")
// if ctrlResp.Seq != 0 {
// responseChan, ok := ongoingRequests[ctrlResp.Seq]
// if ok {
// responseChan <- &ctrlResp
// }
// }
// switch ctrlResp.Event {
// case "video_input_state":
// HandleVideoStateMessage(ctrlResp)
// }
// }
// scopedLogger.Debug().Msg("ctrl sock disconnected")
// }
// func handleVideoClient(conn net.Conn) {
// defer conn.Close()
// scopedLogger := nativeLogger.With().
// Str("addr", conn.RemoteAddr().String()).
// Str("type", "video").
// Logger()
// scopedLogger.Info().Msg("native video socket client connected")
// inboundPacket := make([]byte, maxFrameSize)
// lastFrame := time.Now()
// for {
// n, err := conn.Read(inboundPacket)
// if err != nil {
// scopedLogger.Warn().Err(err).Msg("error during read")
// return
// }
// now := time.Now()
// sinceLastFrame := now.Sub(lastFrame)
// lastFrame = now
// if currentSession != nil {
// err := currentSession.VideoTrack.WriteSample(media.Sample{Data: inboundPacket[:n], Duration: sinceLastFrame})
// if err != nil {
// scopedLogger.Warn().Err(err).Msg("error writing sample")
// }
// }
// }
// }
// // Restore the HDMI EDID value from the config.
// // Called after successful connection to jetkvm_native.
// func restoreHdmiEdid() {
// if config.EdidString != "" {
// nativeLogger.Info().Str("edid", config.EdidString).Msg("Restoring HDMI EDID")
// _, err := CallCtrlAction("set_edid", map[string]interface{}{"edid": config.EdidString})
// if err != nil {
// nativeLogger.Warn().Err(err).Msg("Failed to restore HDMI EDID")
// }
// }
// }