79 lines
2.3 KiB
Go
79 lines
2.3 KiB
Go
// ABOUTME: ControllerGroupRole handles client/command messages
|
|
// ABOUTME: Pushes controller capabilities to joining clients
|
|
package sendspin
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"log"
|
|
|
|
"github.com/Sendspin/sendspin-go/pkg/protocol"
|
|
)
|
|
|
|
// ControllerConfig configures the ControllerGroupRole.
|
|
type ControllerConfig struct {
|
|
// SupportedCommands lists the media commands this server supports
|
|
// (e.g., "next", "previous", "play", "pause").
|
|
SupportedCommands []string
|
|
|
|
// OnCommand is called when a client sends a controller command.
|
|
// May be nil if the caller only wants to push capabilities.
|
|
OnCommand func(client *ServerClient, command string)
|
|
}
|
|
|
|
// ControllerGroupRole handles the "controller" role family. It pushes
|
|
// controller capabilities (supported commands) to clients that
|
|
// advertise the controller role on join, and dispatches incoming
|
|
// client/command payloads to an OnCommand callback.
|
|
type ControllerGroupRole struct {
|
|
config ControllerConfig
|
|
}
|
|
|
|
// NewControllerRole creates a ControllerGroupRole with the given config.
|
|
func NewControllerRole(config ControllerConfig) *ControllerGroupRole {
|
|
return &ControllerGroupRole{config: config}
|
|
}
|
|
|
|
func (r *ControllerGroupRole) Role() string { return "controller" }
|
|
|
|
// OnClientJoin sends controller state (supported commands) to clients
|
|
// that advertise the controller role. Clients without the controller
|
|
// role are skipped.
|
|
func (r *ControllerGroupRole) OnClientJoin(c *ServerClient) {
|
|
if !c.HasRole("controller") {
|
|
return
|
|
}
|
|
|
|
state := protocol.ServerStateMessage{
|
|
Controller: &protocol.ControllerState{
|
|
SupportedCommands: r.config.SupportedCommands,
|
|
},
|
|
}
|
|
|
|
if err := c.Send("server/state", state); err != nil {
|
|
log.Printf("ControllerRole: failed to send state to %s: %v", c.Name(), err)
|
|
}
|
|
}
|
|
|
|
func (r *ControllerGroupRole) OnClientLeave(id string, name string) {}
|
|
|
|
// HandleMessage parses a controller command payload and invokes the
|
|
// OnCommand callback.
|
|
func (r *ControllerGroupRole) HandleMessage(c *ServerClient, payload json.RawMessage) error {
|
|
var cmd struct {
|
|
Command string `json:"command"`
|
|
}
|
|
if err := json.Unmarshal(payload, &cmd); err != nil {
|
|
return fmt.Errorf("invalid controller command: %w", err)
|
|
}
|
|
if cmd.Command == "" {
|
|
return fmt.Errorf("controller command missing 'command' field")
|
|
}
|
|
|
|
if r.config.OnCommand != nil {
|
|
r.config.OnCommand(c, cmd.Command)
|
|
}
|
|
|
|
return nil
|
|
}
|