device

package
v1.8.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 27, 2026 License: MIT Imports: 26 Imported by: 0

Documentation

Overview

Package device discovers media renderers on the local network and speaks their control protocols (DLNA/UPnP AVTransport, Chromecast). The Device interface is deliberately small: the cast pipeline decides what to send (subtitles are burned in upstream), a Device only needs to fetch and play.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func SelfFetches added in v1.8.0

func SelfFetches(t Type) bool

SelfFetches reports whether a renderer of this type fetches media URLs itself (a smart client such as Chromecast, or Roku's channel Video node) versus only playing bytes castor serves to it (DLNA). It is a static property of the protocol, known before the network round-trip of discovery and connect, so the cast pipeline can decide up front that a non-self-fetching renderer will always serve a local spool and begin buffering the single-use source while connect runs concurrently. It MUST agree with the connected renderer's Capabilities().SelfFetch, which the copy-vs-encode stage reads once the device is in hand: each family's media.Renderer literal sets SelfFetch by calling its own selfFetches() rather than re-stating the bool, so the two can't drift independently.

Types

type Config added in v1.8.0

type Config struct {
	Name string
	Type Type

	// Address, when set, pins where the renderer is so a cast connects to it
	// directly and skips discovery. It is what the user configured: a bare host or
	// host:port for any family, or a DLNA device description URL. Locate turns it
	// into the concrete Info each family's connect needs. Empty means "find me by
	// Name over discovery".
	Address string

	Family any
}

Config is the resolved device target the agnostic layers carry and forward: which renderer to reach (Name, Type) plus an opaque Family payload. It names no device family, so core/cast and every other device carry it without knowing any one family exists. The composition root (internal/config) fills Family with the selected family's typed connect settings; only that family's strategy reads it, via a type assertion in its own connect. Family is nil for a family that needs none.

type Device

type Device interface {
	// Play points the renderer at streamURL, advertised as contentType.
	Play(ctx context.Context, streamURL *url.URL, contentType string) error

	// Capabilities reports what this renderer can play: the containers it
	// accepts as-is and the video envelopes it decodes natively. Each device
	// resolves this from itself at connect time (DLNA negotiates it over
	// GetProtocolInfo; Chromecast reports its known receiver profile), so the
	// copy-vs-encode decision follows what the renderer advertises rather than
	// an assumption baked in per device type.
	Capabilities() media.Renderer

	// StreamHeaders returns protocol-specific HTTP headers the local stream
	// server must send when this renderer fetches contentType. Nil when the
	// protocol needs none.
	StreamHeaders(contentType string) map[string]string

	Close() error
}

Device is a connected renderer, ready to play. Obtain one via Connect.

func Connect added in v1.0.0

func Connect(ctx context.Context, info Info, cfg Config) (Device, error)

Connect opens a session to the renderer described by info, dispatching to its family strategy. cfg is forwarded blindly from upstream; only the target family's connect reads its own settings out of cfg.Family.

type Info

type Info struct {
	Name    string
	Type    Type
	Address string
}

func Discover

func Discover(ctx context.Context, timeout time.Duration) ([]Info, error)

Discover scans the local network for renderers of every registered family in parallel (DLNA via SSDP MediaRenderer, Chromecast via mDNS _googlecast._tcp, Roku via SSDP roku:ecp), sharing one timeout window; a family that fails contributes no devices rather than failing the whole scan. Results follow the registry order.

func FindInfo

func FindInfo(ctx context.Context, timeout time.Duration, dtype Type, name string) (Info, error)

func Locate added in v1.8.0

func Locate(ctx context.Context, dtype Type, name, address string) (Info, error)

Locate builds a connectable Info for a renderer whose address is known ahead of time, dispatching to its family strategy so the cast skips discovery entirely. This is the direct-connect path: it serves renderers reachable by unicast but not by discovery, whose SSDP/mDNS is multicast and so crosses no VLAN and is refused where interface enumeration is denied (Android/Termux, where discovery fails with "route ip+net: netlinkrib: permission denied"); it also shortcuts the discovery window for a device at a stable address.

address is what the user pinned: a bare host or host:port for any family, or, for DLNA, its device description URL. Each family turns that into the concrete Info its connect needs; DLNA additionally resolves a bare host to a description URL over a unicast SSDP request. name is carried through as the label and defaults to the host, since a pinned device is not found by name.

type RokuConfig added in v1.8.0

type RokuConfig struct {
	AppID    string `yaml:"app_id"`
	Password string `yaml:"password"`
}

RokuConfig carries what discovery can't: which channel to launch (AppID, the sideloaded "dev" channel by default) and the developer-web-server Password used to sideload Castor's channel the first time. The dev web server's user is always "rokudev", so it is not configurable.

type Type

type Type string
const (
	TypeDLNA       Type = "dlna"
	TypeChromecast Type = "chromecast"
	TypeRoku       Type = "roku"
)

Directories

Path Synopsis
Package rokuchannel builds Castor's Roku channel: a SceneGraph app whose only job is to play a stream URL passed over ECP.
Package rokuchannel builds Castor's Roku channel: a SceneGraph app whose only job is to play a stream URL passed over ECP.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL