76 lines
2.1 KiB
Go
76 lines
2.1 KiB
Go
// Package ipc defines the tiny control protocol shared by the daemon (server)
|
|
// and the CLI/TUI (clients). Messages are newline-delimited JSON over a unix
|
|
// socket, so switching layouts or reading status never requires restarting
|
|
// the video wall.
|
|
package ipc
|
|
|
|
import (
|
|
"bufio"
|
|
"encoding/json"
|
|
"fmt"
|
|
"net"
|
|
"os"
|
|
"path/filepath"
|
|
"strconv"
|
|
"time"
|
|
)
|
|
|
|
// Request is a command sent to the daemon.
|
|
type Request struct {
|
|
Cmd string `json:"cmd"` // "status" | "reload" | "set-layout"
|
|
Name string `json:"name,omitempty"` // layout name for set-layout
|
|
}
|
|
|
|
// SlotStatus reports one grid cell's state.
|
|
type SlotStatus struct {
|
|
Slot int `json:"slot"`
|
|
Camera string `json:"camera"`
|
|
PID int `json:"pid"`
|
|
Running bool `json:"running"`
|
|
Healthy bool `json:"healthy"`
|
|
}
|
|
|
|
// Response is the daemon's reply.
|
|
type Response struct {
|
|
OK bool `json:"ok"`
|
|
Error string `json:"error,omitempty"`
|
|
ActiveLayout string `json:"active_layout,omitempty"`
|
|
Slots []SlotStatus `json:"slots,omitempty"`
|
|
}
|
|
|
|
// SocketPath returns the control socket path inside the runtime dir.
|
|
func SocketPath() string {
|
|
return filepath.Join(RunDir(), "control.sock")
|
|
}
|
|
|
|
// RunDir is the per-user runtime directory for sockets, created on demand.
|
|
func RunDir() string {
|
|
base := os.Getenv("XDG_RUNTIME_DIR")
|
|
if base == "" {
|
|
base = filepath.Join(os.TempDir(), "rtsp-streamer-"+strconv.Itoa(os.Getuid()))
|
|
} else {
|
|
base = filepath.Join(base, "rtsp-streamer")
|
|
}
|
|
return base
|
|
}
|
|
|
|
// Send dials the daemon, sends one request, and returns the reply.
|
|
func Send(req Request) (*Response, error) {
|
|
conn, err := net.DialTimeout("unix", SocketPath(), 3*time.Second)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("cannot reach daemon (is it running?): %w", err)
|
|
}
|
|
defer conn.Close()
|
|
_ = conn.SetDeadline(time.Now().Add(5 * time.Second))
|
|
|
|
enc := json.NewEncoder(conn)
|
|
if err := enc.Encode(req); err != nil {
|
|
return nil, err
|
|
}
|
|
var resp Response
|
|
if err := json.NewDecoder(bufio.NewReader(conn)).Decode(&resp); err != nil {
|
|
return nil, err
|
|
}
|
|
return &resp, nil
|
|
}
|