diff --git a/.gitea/workflows/build-arm64.yml b/.gitea/workflows/build-arm64.yml index 02cfa69..875df25 100644 --- a/.gitea/workflows/build-arm64.yml +++ b/.gitea/workflows/build-arm64.yml @@ -25,7 +25,8 @@ jobs: go vet ./... mkdir -p dist GOOS=linux GOARCH=arm64 go build -trimpath -ldflags='-s -w' -o dist/groundstation-linux-arm64 ./cmd/groundstation - tar -C dist -czf dist/groundstation-linux-arm64.tar.gz groundstation-linux-arm64 + GOOS=linux GOARCH=arm64 go build -trimpath -ldflags='-s -w' -o dist/groundstation-display-linux-arm64 ./cmd/groundstation-display + tar -C dist -czf dist/groundstation-linux-arm64.tar.gz groundstation-linux-arm64 groundstation-display-linux-arm64 sha256sum dist/groundstation-linux-arm64.tar.gz > dist/groundstation-linux-arm64.tar.gz.sha256 sha256sum dist/groundstation-linux-arm64 diff --git a/cmd/groundstation-display/main.go b/cmd/groundstation-display/main.go new file mode 100644 index 0000000..428f50f --- /dev/null +++ b/cmd/groundstation-display/main.go @@ -0,0 +1,71 @@ +package main + +import ( + "fmt" + "log" + "os" + "os/exec" + + "github.com/BurntSushi/xgb" + "github.com/BurntSushi/xgb/xproto" +) + +const ( + width = 1920 + height = 1080 +) + +func main() { + conn, err := xgb.NewConn() + if err != nil { + log.Fatal(err) + } + defer conn.Close() + + screen := xproto.Setup(conn).DefaultScreen(conn) + window, err := xproto.NewWindowId(conn) + if err != nil { + log.Fatal(err) + } + + values := uint32(xproto.CwBackPixel | xproto.CwEventMask) + xproto.CreateWindow(conn, screen.RootDepth, window, screen.Root, 0, 0, width, height, 0, + xproto.WindowClassInputOutput, screen.RootVisual, values, + []uint32{screen.BlackPixel, xproto.EventMaskExposure}) + xproto.MapWindow(conn, window) + conn.Sync() + + // XFCE owns the actual fullscreen policy; use its existing wmctrl helper. + _ = exec.Command("wmctrl", "-i", "-r", fmt.Sprintf("0x%08x", window), "-b", "add,fullscreen").Run() + + gc, err := xproto.NewGcontextId(conn) + if err != nil { + log.Fatal(err) + } + xproto.CreateGC(conn, gc, xproto.Drawable(window), xproto.GcForeground|xproto.GcBackground, + []uint32{screen.WhitePixel, screen.BlackPixel}) + font := xproto.Font(window) + xproto.OpenFont(conn, font, uint16(len("fixed")), "fixed") + xproto.ChangeGC(conn, gc, xproto.GcFont, []uint32{uint32(font)}) + + draw := func() { + xproto.ClearArea(conn, false, window, 0, 0, width, height) + message := "Brak polaczenia WFB" + xproto.ImageText8(conn, byte(len(message)), xproto.Drawable(window), gc, 32, 56, message) + conn.Sync() + } + draw() + + for { + event, err := conn.WaitForEvent() + if err != nil { + if os.IsTimeout(err) { + continue + } + return + } + if _, ok := event.(xproto.ExposeEvent); ok { + draw() + } + } +} diff --git a/cmd/groundstation/main.go b/cmd/groundstation/main.go index 55fbeee..6d6be75 100644 --- a/cmd/groundstation/main.go +++ b/cmd/groundstation/main.go @@ -8,6 +8,7 @@ import ( "io" "log" "os" + "os/exec" "os/signal" "path/filepath" "syscall" @@ -37,6 +38,15 @@ func main() { ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM) defer stop() + if display, err := startDisplay(); err != nil { + log.Printf("display start deferred: %v", err) + } else { + defer func() { + _ = display.Process.Signal(os.Interrupt) + _ = display.Wait() + }() + } + var video *videoController if cfg.Video.Enabled { video = newVideoController(cfg.Video.Command) @@ -70,6 +80,16 @@ func main() { } } +func startDisplay() (*exec.Cmd, error) { + cmd := exec.Command("runuser", "-u", "orangepi", "--", "env", + "DISPLAY=:0", "XAUTHORITY=/home/orangepi/.Xauthority", "groundstation-display") + cmd.Stdout, cmd.Stderr = os.Stdout, os.Stderr + if err := cmd.Start(); err != nil { + return nil, err + } + return cmd, nil +} + func setupLogger(cfg config.Config) (*log.Logger, func(), error) { writers := []io.Writer{os.Stdout} closeLog := func() {} diff --git a/go.mod b/go.mod index 7963d84..f4a69e5 100644 --- a/go.mod +++ b/go.mod @@ -3,6 +3,7 @@ module git.piksar.eu/piotr/groundstation go 1.24.0 require ( + github.com/BurntSushi/xgb v0.0.0-20210121224620-deaf085860bc golang.org/x/sys v0.40.0 gopkg.in/yaml.v3 v3.0.1 ) diff --git a/go.sum b/go.sum index 2ed8652..91b96fe 100644 --- a/go.sum +++ b/go.sum @@ -1,3 +1,5 @@ +github.com/BurntSushi/xgb v0.0.0-20210121224620-deaf085860bc h1:7D+Bh06CRPCJO3gr2F7h1sriovOZ8BMhca2Rg85c2nk= +github.com/BurntSushi/xgb v0.0.0-20210121224620-deaf085860bc/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= golang.org/x/sys v0.40.0 h1:DBZZqJ2Rkml6QMQsZywtnjnnGvHza6BTfYFWY9kjEWQ= golang.org/x/sys v0.40.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=