Help us shape the future of Go! Take the 2026 Go Developer Survey

frontend

package
v0.3.0 Latest Latest
Warning

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

Go to latest
Published: Nov 1, 2026 License: GPL-3.0 Imports: 19 Imported by: 0

Documentation

Overview

Package frontend defines the protocol-facing contracts provided by Ether.

Index

Constants

View Source
const (
	ImagePoster   = "poster"
	ImageBackdrop = "backdrop"
	ImageThumb    = "thumb"
	ImageBanner   = "banner"
	ImageStill    = "still"
	ImagePerson   = "person"
	ImageChannel  = "channel"
)
View Source
const (
	KindShow    = core.KindShow
	KindSeason  = core.KindSeason
	KindEpisode = core.KindEpisode
	KindExtra   = core.KindExtra
)

Catalogue key kinds and constructors stay owned by core. Adapters compare and rebuild parent keys through these aliases.

View Source
const LibraryCollagePrefix = "library-collage/"

LibraryCollagePrefix marks a generated library-view collage. The remainder is the hex identity of the view and the child posters it was built from.

View Source
const SeriesNextUpLimit = 1000

SeriesNextUpLimit is the indexed window for one series' next-up listing. The lookup is keyed by the series, never the library.

Variables

View Source
var (
	ErrPartyNotFound  = errors.New("watch party not found")
	ErrPartyForbidden = errors.New("watch party forbidden")
	ErrPartyDenied    = errors.New("watch party denied")
	ErrPartyConflict  = errors.New("watch party conflict")
)

Watch-party failures are safe to show a client. They do not include the title a viewer is not allowed to see.

View Source
var ErrAlreadyMounted = errors.New("frontend already mounted")
View Source
var ErrBadPlaylist = errors.New("invalid playlist request")

ErrBadPlaylist is an invalid playlist name, index, or empty change.

View Source
var ErrIdentityUnavailable = errors.New("frontend identity operation unavailable")

ErrIdentityUnavailable means this host does not implement credential issuance.

View Source
var ErrImageBatchLimit = errors.New("frontend: invalid artwork batch")
View Source
var ErrInvalidPreferences = errors.New("invalid frontend preferences")
View Source
var ErrNotAvailable = core.ErrNotAvailable

ErrNotAvailable means the host has no service for this browse feature. It shares identity with the domain error for errors.Is checks.

View Source
var ErrNotFound = core.ErrNotFound

ErrNotFound identifies an absent or inaccessible frontend resource. It shares identity with the domain error for errors.Is checks.

View Source
var ErrNotRegistered = errors.New("frontend not registered")
View Source
var ErrPeopleQuery = errors.New("frontend: invalid people query")
View Source
var ErrPreferencesLimit = errors.New("frontend preferences limit exceeded")
View Source
var ErrPreferencesNotFound = core.ErrNotFound

ErrPreferencesNotFound identifies a missing record without exposing storage.

View Source
var ErrQuickConnectPending = errors.New("frontend quick connect pending")

ErrQuickConnectPending means the code has not yet been approved.

View Source
var ErrRateLimited = errors.New("frontend identity rate limited")

ErrRateLimited means the verified network peer has exceeded an identity limit.

View Source
var ErrRowViewStale = errors.New("frontend: row view snapshot expired or changed")

ErrRowViewStale asks the client to refresh its visit-scoped row views.

View Source
var ErrSessionBusy = errors.New("session operation capacity exhausted")

ErrSessionBusy means bounded broker admission is temporarily exhausted.

View Source
var ErrSourceGone = errors.New("frontend: offered playback source is gone")

ErrSourceGone means previously offered source facts no longer match a playable source; the client must request fresh detail.

View Source
var ErrTrackNotFound = errors.New("selected track is not available")

ErrTrackNotFound reports that an explicit selection does not identify one stream in the opened source.

View Source
var ErrTrackSourceUnavailable = errors.New("verified track source unavailable")

ErrTrackSourceUnavailable reports that the broker cannot prove the opened source and its track layout across planning and playback admission.

View Source
var ErrTranscodeCapacity = errors.New("transcode capacity exhausted")

ErrTranscodeCapacity classifies an exhausted shared encoder budget.

View Source
var ErrUnauthorized = core.ErrUnauthorized

ErrUnauthorized identifies a viewer who cannot see or change the resource. It shares identity with the domain error for errors.Is checks.

Functions

func AdvertisedName

func AdvertisedName(settings Settings) string

AdvertisedName is the household name a frontend shows. The app fills serverName from the general server name; a frontend does not keep its own.

func ApplyDetailHeader

func ApplyDetailHeader(tagline, overview, header string) (string, string)

ApplyDetailHeader places a viewer's micro-reason the way Plex detail does. An empty tagline takes the header, which is the line under the title. Otherwise the header prefixes the overview and the catalogue tagline stays. The header is never written into both places. An empty header changes nothing.

func ArtworkTitle

func ArtworkTitle(ctx context.Context, key core.RatingKey) (*core.Title, bool)

ArtworkTitle returns the title stored by WithArtworkTitle when it is the requested key.

func ClientIP

func ClientIP(ctx context.Context) (netip.Addr, bool)

ClientIP returns the verified peer carried by WithClientIP.

func DefaultPort

func DefaultPort(id Protocol) (int, bool)

DefaultPort returns the listener port for protocols that require one. Silo uses its Compose default; the reference lab's 8098 is an override.

func KnownSDR

func KnownSDR(stream StreamInfo) bool

KnownSDR is Emby's evidence rule for an SDR picture. An explicit SDR transfer curve is enough. With no transfer at all, 8-bit 4:2:0 is SDR once the caller knows Dolby Vision is absent and the transfer is not PQ. Other pixel formats, depths, and unrecognised curves stay unlabelled.

func LatestPlayedFilter

func LatestPlayedFilter(ctx context.Context) (played bool, ok bool)

LatestPlayedFilter reports whether Latest should filter on played state.

func NormalizeLanguage

func NormalizeLanguage(tag string) string

NormalizeLanguage folds a client language tag to the form Ether stores.

func QuietIdentity

func QuietIdentity(ctx context.Context) bool

QuietIdentity reports whether activity writes should be skipped.

func SameImage

func SameImage(a, b Image) bool

SameImage compares stable authorization identity, excluding optional metadata.

func SynchronousArtworkDeadline

func SynchronousArtworkDeadline(ctx context.Context) (time.Time, bool)

SynchronousArtworkDeadline is the time after which artwork hashing returns to the background worker. The second result is false when no budget was set.

func WithArtworkTitle

func WithArtworkTitle(ctx context.Context, title *core.Title) context.Context

WithArtworkTitle carries a title the caller already loaded and authorized. Artwork listing must not read that title again.

func WithClientIP

func WithClientIP(ctx context.Context, ip netip.Addr) context.Context

WithClientIP supplies the verified network peer for authentication rate limits. A frontend must derive it from the transport and trusted proxies, never an untrusted forwarding header. Missing or invalid addresses fail closed.

func WithLatestPlayed

func WithLatestPlayed(ctx context.Context, played bool) context.Context

WithLatestPlayed records the Latest IsPlayed filter. False keeps only unplayed items. Jellyfin and Emby both do that when the query omits IsPlayed and the user still has the default HidePlayedInLatest setting.

func WithQuietIdentity

func WithQuietIdentity(ctx context.Context) context.Context

WithQuietIdentity tells credential resolution to skip activity writes. Sign-in uses it so the response is not waiting on viewer-times bookkeeping.

func WithRequestMemo

func WithRequestMemo(ctx context.Context) context.Context

WithRequestMemo installs the per-request viewer and visibility memo.

func WithSynchronousArtworkMetadata

func WithSynchronousArtworkMetadata(ctx context.Context, budget time.Duration) context.Context

WithSynchronousArtworkMetadata lets a caller wait briefly for hashing that is already in flight. Stored rows are joined without this budget. The page cache clears it before filling a page, so a browse never holds the cache open for a hash.

func WithoutSynchronousArtworkMetadata

func WithoutSynchronousArtworkMetadata(ctx context.Context) context.Context

WithoutSynchronousArtworkMetadata drops an in-flight artwork wait so a caller, such as the browse page cache, returns as soon as stored rows are joined.

Types

type ActivityPage

type ActivityPage struct {
	Items      []Title
	Total      int
	TotalExact bool
	More       bool
}

ActivityPage reports an exact total only when TotalExact is true; otherwise Total is a lower bound and More indicates that another page is available.

type AiredMemo

type AiredMemo struct {
	Items []core.Title
	Total int
	Err   error
}

AiredMemo is one show's capped local episode page. Season rows on the same request share it instead of reading the show again for every season.

type Announcer

type Announcer interface {
	Start(context.Context) error
	Close() error
}

type Artwork

type Artwork interface {
	List(context.Context, ArtworkRequest) (images []Image, complete bool, err error)
	Read(context.Context, ArtworkRequest, Image, ArtworkTransform) (data []byte, contentType string, err error)
}

Artwork is the host-side source of authorized descriptors and their bytes. An implementation reports complete when its currently selected artwork is authoritative, including on a cold cache. Alternatives may arrive later. It must recheck visibility and descriptor membership on Read; the descriptor is a reference, not an authorization credential.

type ArtworkOwner

type ArtworkOwner struct {
	Item          RatingKey
	Images        []Image
	Authoritative bool
}

ArtworkOwner identifies the independently authorized item whose descriptors must be passed to ImageGrants. Incomplete lists must not be granted.

type ArtworkRequest

type ArtworkRequest struct {
	Viewer *core.Viewer
	Device core.Device
	Item   core.RatingKey
	// Channel is a stable LiveTV channel ID. Exactly one of Item and Channel
	// identifies the subject.
	Channel string
}

ArtworkRequest identifies the viewer and presentation context for artwork. Implementations must apply the same item visibility policy as Experience.

type ArtworkTransform

type ArtworkTransform struct {
	Width, Height int
	Format        string
	Blur          bool
}

ArtworkTransform describes the requested output. Zero dimensions preserve the source's normal dimensions; Format is empty, "jpeg", or "png".

type AuthenticatedLazyStreams

type AuthenticatedLazyStreams interface {
	ServeAuthenticated(http.ResponseWriter, *http.Request, string, PlanRequest)
}

AuthenticatedLazyStreams is the optional WebDAV-style capability for a surface that authenticates each GET and HEAD instead of issuing a bearer URL.

type Capabilities

type Capabilities interface {
	Build(context.Context, CapabilityRequest) (CapabilityResult, error)
}

Capabilities applies client declarations, device quirks and owner rules.

type CapabilityRequest

type CapabilityRequest struct {
	Viewer       *core.Viewer
	Device       caps.DeviceInfo
	Profile      caps.DeviceProfile
	ProtocolInfo []string
	UserAgent    string
}

CapabilityRequest describes client declarations, not a claim about playback. Viewer must come from the authenticated session when user rules are desired. Build requires WithClientIP using Host.ClientIP on the current request; the host derives network locality and ignores the caller's Remote claim.

type CapabilityResult

type CapabilityResult struct {
	Client  core.ClientCaps
	Quality core.QualityProfile
}

CapabilityResult pairs client playback capabilities with the selected owner quality profile. The profile does not grant additional hardware capabilities.

type CertifiedApp

type CertifiedApp struct {
	Name  string        `json:"name"`
	Steps []ConnectStep `json:"steps"`
}

CertifiedApp contains only verified native clients, with their connection steps.

type CinemaIntros

type CinemaIntros interface {
	Trailers(context.Context, *core.Viewer, core.Device, core.RatingKey, int) ([]Extra, error)
}

CinemaIntros returns playable trailers of other visible, unwatched movies to play before feature. An empty slice means cinema intros are off or none match.

type ClientCaps

type ClientCaps = core.ClientCaps

type Collection

type Collection = core.Collection

type CollectionPage

type CollectionPage struct {
	Items []core.Collection
	Total int
}

type CollectionQuery

type CollectionQuery struct {
	Types         []core.MediaType
	Offset, Limit int
}

CollectionQuery requests viewer-scoped collection pagination. A nonpositive Limit defaults to 50; larger requests are capped at 500.

type Command

type Command struct {
	Kind                CommandKind
	Position            time.Duration
	StreamIndex         int
	Message             string
	ControllerSessionID string
}

type CommandKind

type CommandKind string
const (
	CommandStop        CommandKind = "stop"
	CommandPause       CommandKind = "pause"
	CommandUnpause     CommandKind = "unpause"
	CommandSeek        CommandKind = "seek"
	CommandSetAudio    CommandKind = "setAudio"
	CommandSetSubtitle CommandKind = "setSubtitle"
	CommandMessage     CommandKind = "message"
)

type ConnectStep

type ConnectStep string

ConnectStep identifies a translated owner-console connection instruction.

const (
	ConnectOpenApp      ConnectStep = "openApp"
	ConnectAddServer    ConnectStep = "addServer"
	ConnectSignIn       ConnectStep = "signIn"
	ConnectInstallAddon ConnectStep = "installAddon"
)

type Continuation

type Continuation string

Continuation distinguishes a known next page from exhaustion and a truncated source that cannot determine whether more matches exist.

const (
	ContinuationMore      Continuation = "more"
	ContinuationExhausted Continuation = "exhausted"
	ContinuationUnknown   Continuation = "unknown"
)

type DecideOptions

type DecideOptions = core.DecideOptions

type Decision

type Decision = core.Decision

type Descriptor

type Descriptor struct {
	ID             Protocol       `json:"id"`
	Name           string         `json:"name"`
	Version        string         `json:"version,omitempty"`
	DocsURL        string         `json:"docsUrl,omitempty"`
	DefaultPort    int            `json:"defaultPort,omitempty"`
	Clients        []string       `json:"clients,omitempty"`
	CertifiedApps  []CertifiedApp `json:"certifiedApps,omitempty"`
	SettingsSchema any            `json:"settingsSchema,omitempty"`
}

type DetailFacts

type DetailFacts struct {
	Header       string
	RatingsKnown bool
	Community    *float64
	Critic       *float64
	Sources      []ExternalRating
}

DetailFacts is per-viewer detail copy and provider ratings for one title. Header is empty when micro-reasons are off or the taste model is too thin to state a match. RatingsKnown means the ratings provider is on: Community and Critic are nil when that source has no cached value, and callers must not substitute the catalogue score. Community is 0–10. Critic is 0–100.

type DetailFactsSource

type DetailFactsSource interface {
	DetailFacts(context.Context, *core.Viewer, core.Title) DetailFacts
	PageRatings(context.Context, *core.Viewer, []core.Title) map[core.RatingKey]DetailFacts
}

DetailFactsSource is optional. Experience implementations that do not personalize detail copy leave the interface unimplemented.

type DetailPlanner

type DetailPlanner interface {
	DetailPlan(ctx context.Context, request PlanRequest) (PlayPlan, error)
	ResolveDetailSource(ctx context.Context, scope VersionScope, handle string) (DetailSourceTarget, error)
	MatchDetailSession(ctx context.Context, scope VersionScope, handle, sessionID string) error
}

DetailPlanner resolves a playable single item within a bounded admission budget. It returns source facts without creating a frontend session. The caller must separately obtain a scoped lazy stream capability.

type DetailSourceTarget

type DetailSourceTarget struct {
	Item RatingKey
	ETag string
}

type Device

type Device = core.Device

func LANDevice

func LANDevice(peer netip.Addr) Device

LANDevice derives a stable DLNA device identity from the verified network peer, never from a client-supplied forwarding header or device identifier.

type DeviceIdentity

type DeviceIdentity interface {
	ResolveDevice(context.Context, string, Device) (*Viewer, time.Time, error)
}

DeviceIdentity optionally validates a credential against its stored device and returns the grant's current absolute expiry. This read-only operation does not extend the grant or write activity on media segment requests.

type DiscoveryRequest

type DiscoveryRequest struct {
	Data     []byte
	Peer     netip.AddrPort
	Endpoint string
}

DiscoveryRequest describes a LAN datagram and this surface's verified, reachable base address. Data is a private copy and contains no credentials.

type DiscoveryResponder

type DiscoveryResponder interface {
	RespondDiscovery(context.Context, DiscoveryRequest) ([]byte, bool)
}

DiscoveryResponder is optional on an Instance. The host multiplexes its responses through a single UDP listener and unregisters it on unmount. Implementations return false for unmatched probes or disabled discovery.

type EditionBatch

type EditionBatch interface {
	EditionsMany(context.Context, *core.Viewer, core.Device, []core.RatingKey) (map[core.RatingKey][]Version, error)
}

EditionBatch resolves local copies for a page in one lookup.

type Editions

type Editions interface {
	Editions(context.Context, *core.Viewer, core.Device, core.RatingKey) ([]Version, error)
}

Editions is an optional local-media catalogue. Implementations return probed copies already on disk and do not search indexers.

type Event

type Event struct {
	Type     string
	ViewerID int64
	// ActorViewerID is set from the authenticated actor for SessionCommand;
	// zero denotes a system-originated stop without an authenticated actor.
	ActorViewerID int64
	Item          core.RatingKey
	SessionID     string
	// SubjectKind and SubjectID identify non-title user data such as a
	// favorite person, collection or channel. Item remains the title key.
	SubjectKind     string
	SubjectID       string
	OriginProtocol  Protocol
	OriginSessionID string
	OriginClientID  string
	Command         *Command
	TargetProtocol  Protocol
	TargetDeviceID  string
	Session         *Session
	Timeline        *Timeline
}

type EventScope

type EventScope struct {
	Viewer *core.Viewer
	Owner  bool
	// Protocol suppresses this surface's own user-data invalidations.
	Protocol Protocol
	// SessionID selects the authenticated client session for targeted commands.
	SessionID string
	// Device binds a socket before a playback session exists and remains valid
	// when this authenticated device's current session changes.
	Device core.Device
}

Owner requests owner scope; the subscriber must verify active owner status.

type Experience

type Experience interface {
	Views(context.Context, *core.Viewer) ([]View, error)
	Collections(context.Context, *core.Viewer, core.Device, CollectionQuery) (CollectionPage, error)
	NotInterested(context.Context, *core.Viewer, core.Device, PageQuery) (NotInterestedPage, error)
	NotInterestedItem(context.Context, *core.Viewer, core.Device, core.RatingKey) (NotInterestedEntry, error)
	// ResolveExternal resolves an IMDb ID without opening a release, and returns
	// a key only after enforcing current viewer and inherited-show policy.
	ResolveExternal(context.Context, *core.Viewer, core.Device, ExternalRequest) (core.RatingKey, error)
	Rows(context.Context, RowRequest) ([]Row, error)
	Item(context.Context, ItemRequest) (ItemDetail, error)
	Children(context.Context, *core.Viewer, core.Device, core.RatingKey, ItemQuery) (core.Page, error)
	LibraryItems(context.Context, *core.Viewer, core.Device, string, ItemQuery) (core.Page, error)
	Similar(context.Context, *core.Viewer, core.Device, core.RatingKey, ItemQuery) (SearchPage, error)
	Ancestors(context.Context, *core.Viewer, core.Device, core.RatingKey) ([]core.Title, error)
	Facets(context.Context, *core.Viewer, core.Device, string, string) ([]core.FacetValue, error)
	ResolveFacet(context.Context, *core.Viewer, core.Device, string, string, string) (core.FacetValue, error)
	// PersonFacetIDs returns IDs only for credited people of an authorized title.
	// Episode-only credits may not appear in library-wide Facets or ResolveFacet.
	// Requests are bounded to 256 positive TMDB IDs; missing credits are omitted.
	PersonFacetIDs(context.Context, *core.Viewer, core.Device, core.RatingKey, []int64) (map[int64]string, error)
	// NamedFacetIDs resolves exact genre or studio names on one visible title.
	// A request contains at most 256 nonempty names; missing names are omitted.
	NamedFacetIDs(context.Context, *core.Viewer, core.Device, core.RatingKey, string, []string) (map[string]string, error)
	Search(context.Context, *core.Viewer, core.Device, string, ItemQuery) (SearchPage, error)
	UserData(context.Context, *core.Viewer, []core.RatingKey) (map[core.RatingKey]core.WatchStatus, error)
	SetPlayed(context.Context, *core.Viewer, core.RatingKey) error
	SetUnplayed(context.Context, *core.Viewer, core.RatingKey) error
	SetFavorite(context.Context, *core.Viewer, core.RatingKey, bool) error
	SetNotInterested(context.Context, *core.Viewer, core.RatingKey, bool) error
	SetWatchlist(context.Context, *core.Viewer, core.RatingKey, bool) error
	SetEntityFavorite(context.Context, *core.Viewer, FavoriteRef, bool) error
	EntityFavorites(context.Context, *core.Viewer, []FavoriteRef) (map[FavoriteRef]bool, error)
	ResolveEventSubject(context.Context, *core.Viewer, core.Device, FavoriteRef) (ResolvedEventSubject, error)
	SetRating(context.Context, *core.Viewer, core.RatingKey, float64) error
	SetLikes(context.Context, *core.Viewer, core.RatingKey, *bool) error
	RemoveFromContinue(context.Context, *core.Viewer, core.RatingKey) error
}

Experience applies viewer policy before returning any data. Browse operations must not resolve or open a release. Policy is applied before pagination and limits.

type ExternalRating

type ExternalRating struct {
	Source, Name, Display string
	Score                 float64
	Votes                 int64
}

ExternalRating is one provider score a client can name. Score is 0–100. Display is the source's own scale ("8.2", "94%"). Votes is zero when the provider did not report a count.

type ExternalRequest

type ExternalRequest struct {
	Source          string
	ID              string
	Type            core.MediaType
	Season, Episode *int
}

ExternalRequest identifies an IMDb title with an optional canonical episode. Season and Episode must either both be set or both omitted.

type Extra

type Extra struct {
	Key, ParentKey                          core.RatingKey
	Title, Kind, Source, SourceID, Language string
	Official                                bool
	PublishedAt                             time.Time
	Duration                                time.Duration
	Height                                  int
}

Extra describes a playable trailer or clip. Key is the broker-facing item identity; Source and SourceID describe the upstream reference, not a resolved URL or credentials. Plex media and part identifiers remain adapter-owned.

type ExtraStreams

type ExtraStreams interface {
	Lookup(core.RatingKey) (Extra, bool)
	Open(context.Context, core.RatingKey) (container, rawURL string, headers map[string]string, err error)
}

ExtraStreams resolves a playable trailer or clip the extras service registered. Open returns a direct media URL. Callers authorize the parent before Open.

type FavoriteKind

type FavoriteKind string

FavoriteKind namespaces stable, policy-checked entity identifiers.

const (
	FavoriteTitle      FavoriteKind = "title"
	FavoritePerson     FavoriteKind = "person"
	FavoriteCollection FavoriteKind = "collection"
	FavoriteChannel    FavoriteKind = "channel"
)

type FavoriteRef

type FavoriteRef struct {
	Kind FavoriteKind
	ID   string
}

FavoriteRef identifies an entity in its own namespace.

type Frontend

type Frontend interface {
	Describe() Descriptor
	Mount(context.Context, Host) (Instance, error)
}

type GrantDeviceIdentity

type GrantDeviceIdentity interface {
	ResolveGrantDevice(context.Context, string, string) (*Viewer, Device, time.Time, error)
}

GrantDeviceIdentity retrieves the stored binding for a surface credential. An empty claim permits token-only requests; a nonempty claim must match the stored device ID. The operation never extends the grant or writes activity.

type GrantedImage

type GrantedImage struct {
	Image  Image
	Secret string
}

type HLSSession

type HLSSession = core.HLSSession

type Host

type Host struct {
	Experience         Experience
	ViewerCapabilities ViewerCapabilitiesFunc
	ViewerPolicy       ViewerPolicy
	Capabilities       Capabilities
	Preferences        Preferences
	TrackPreferences   TrackPreferenceService
	LiveTV             LiveTV
	VirtualPaths       VirtualPaths
	Sessions           Sessions
	LastPlayedSource   LastPlayedSourceReader
	SourceOffers       SourceOffers
	VersionHandles     VersionHandles
	// Editions lists locally probed copies of one title. It is empty when the
	// process has no local media manifest, and it must not search the network.
	Editions    Editions
	LazyStreams LazyStreams
	LANStreams  LANLazyStreams
	Identity    SurfaceIdentity
	IDs         ids.Codecs
	Events      Subscriber
	Tickets     Tickets
	// WatchParty is the shared Silo and Jellyfin room. Nil leaves both off.
	WatchParty  WatchParty
	Images      Images
	ImageGrants ImageGrants
	// Artwork serves the same composited poster bytes the other frontends
	// grant. DLNA has no credential, so it reads this after LANViewer.
	Artwork Artwork
	// ExtraStreams opens a playable trailer or extra. Nil means extras are not
	// configured; listing routes still authorize the parent and return nothing.
	ExtraStreams ExtraStreams
	// DirectProxy selects the proxy for trailer fetches. Nil follows the
	// process environment. The app wires the direct route so frontends do
	// not import the egress policy.
	DirectProxy func(*http.Request) (*url.URL, error)
	// Cinema lists preroll trailers of other movies. Nil means cinema intros
	// are not wired; the intros route returns an empty page after authorization.
	Cinema CinemaIntros
	// Subtitles searches and downloads a sidecar only after an explicit pick.
	// Nil or Enabled false tells clients the server will not fetch one.
	Subtitles SubtitleCatalog
	Config    func() Settings
	// MetadataLanguage is the catalog language (config catalog.language).
	// Empty skips that step of the no-list audio chain.
	MetadataLanguage func() string
	// AudioOrder is the shared no-choice language chain. Frontends call it
	// instead of importing the track-preference package. Nil keeps the
	// caller's own fallback.
	AudioOrder func(audio []string, server, original string, preferOriginal bool) []string
	// PickAudio returns a stream position in MediaInfo, or -1 when no audio
	// stream exists. Nil keeps the caller's own fallback.
	PickAudio func(MediaInfo, []string) int
	Log       *slog.Logger
	// ViewerPortalURL returns a reachable owner-selected viewer portal URL for this client.
	ViewerPortalURL func(context.Context, *http.Request) (string, error)
	// SecurePortalURL selects a verified reachable HTTPS portal address.
	SecurePortalURL func(context.Context, *http.Request) (string, error)
	// SurfaceURL returns a reachable, verified base for this frontend's routes.
	SurfaceURL func(context.Context, *http.Request) (string, error)
	// LANViewer resolves the owner-selected active DLNA viewer only after
	// trusted-proxy-aware network classification; other surfaces receive nil.
	LANViewer func(context.Context, *http.Request) (*Viewer, error)
	// ClientSeen reports an authenticated client's protocol-specific device ID.
	ClientSeen func(deviceID string)
	// ClientIP resolves the transport peer using the configured trusted proxies.
	ClientIP func(*http.Request) (netip.Addr, bool)
	// PageFreshness invalidates cached browse bodies. Nil disables the cache.
	PageFreshness func() PageFreshness
	// PersonalHomes keeps the last personalized library list so the first
	// UserViews after a restart can include it. Nil keeps that list in memory.
	PersonalHomes PersonalHomeStore
}

type Image

type Image struct {
	Kind, Path, Tag string
	// Subject identifies an entity within the authorized item, such as the
	// tmdb:<id> person whose credit owns a portrait. It is part of the grant.
	Subject string
	// Width and Height describe the cached source pixels; zero means unknown.
	Width, Height int
	// BlurHash is a cached preview of the source; empty means unavailable.
	BlurHash string
	// ThumbHash is padded base64 of the cached source's standard ThumbHash;
	// empty means the background computation has not completed.
	ThumbHash string
}

Image identifies an image authorized for an item. Path is an opaque, server-owned source reference: callers must neither interpret it as a URL nor construct one themselves. Tag changes when the selected artwork changes. Older adapters may still return a TMDB path while migrating to opaque refs.

type ImageBatchItem

type ImageBatchItem struct {
	Item          core.RatingKey
	Authoritative bool
	Images        []GrantedImage
}

type ImageBatchRequest

type ImageBatchRequest struct {
	Credential string
	Device     core.Device
	Items      []core.RatingKey
	Kinds      []string
}

ImageBatchRequest requests primary artwork for a page of items. At most 50 distinct keys and 256 input keys are accepted; duplicates are removed in first-occurrence order. Empty Kinds selects poster. Person and channel images are deliberately excluded and must use their scoped single grant.

type ImageGrantBatch

type ImageGrantBatch interface {
	IssueBatch(context.Context, ImageBatchRequest) ([]ImageBatchItem, error)
}

ImageGrantBatch is an optional extension for rows and grids. Hidden items are omitted. Results preserve first-occurrence item and descriptor order; each requested kind contributes at most its first descriptor. An authorized item with no images is distinguished from an unavailable artwork list by Authoritative. Every secret is independently revalidated when served.

type ImageGrantRequest

type ImageGrantRequest struct {
	Credential string
	Device     core.Device
	Item       core.RatingKey
	Channel    string
	Image      Image
}

ImageGrantRequest asks for one authorized image on one authenticated session. Credential is supplied in-process and must never be placed in an image URL.

type ImageGrants

type ImageGrants interface {
	Issue(context.Context, ImageGrantRequest) (string, error)
	Revoke(context.Context, string, string) error
	Serve(http.ResponseWriter, *http.Request, string)
}

ImageGrants issues and validates short-lived opaque image capabilities. Serve requires a capability, even when the client cannot send account tokens.

type ImagePageRequest

type ImagePageRequest struct {
	Credential string
	Device     core.Device
	Titles     []core.Title
	Kinds      []string
}

ImagePageRequest signs artwork for titles the caller has already authorized for this page. The signer does not write a grant row.

type ImagePageSigner

type ImagePageSigner interface {
	SignPage(context.Context, ImagePageRequest) ([]ImageBatchItem, error)
}

ImagePageSigner is the list path for image URLs. Serve still rechecks the credential, expiry, revocation and current artwork policy.

type Images

type Images interface {
	ServeHTTP(http.ResponseWriter, *http.Request)
}

Images serves TMDB artwork via GET or HEAD with query parameters path and w. Frontends must authorize access to the item before calling it.

type Instance

type Instance interface {
	Handler() http.Handler
	Listeners() []ListenerSpec
	Discovery() []Announcer
	Status(context.Context) Status
	Close(context.Context) error
}

type ItemArtwork

type ItemArtwork interface {
	ItemArtwork(context.Context, *core.Viewer, core.Device, core.RatingKey) ([]Image, bool, error)
}

ItemArtwork is an optional cache-only authorization path for issuing grid artwork without computing playback versions or tracks.

type ItemArtworkPage

type ItemArtworkPage interface {
	ItemArtworkPage(context.Context, *core.Viewer, core.Device, []core.RatingKey) (map[core.RatingKey][]Image, error)
}

ItemArtworkPage authorizes and lists artwork for one grid in a batch. SignPage uses it so a home page does not load each title on its own.

type ItemDetail

type ItemDetail struct {
	Collection *core.Collection
	Playlist   *core.Playlist
	Title      core.Title
	UserData   core.WatchStatus
	// CanPlay reflects current playback authorization when known. Nil means the
	// verified peer or policy result is unavailable. It does not guarantee a
	// source, codec, stream slot or transcode capacity will be available.
	CanPlay *bool
	Tracks  []core.StreamInfo
	// TracksEstimated marks a set containing synthesized playback estimates.
	// These streams must not be presented as facts about a resolved source.
	TracksEstimated bool
	Images          []Image
	// ImagesAuthoritative reports whether Images describes the currently selected
	// authorized artwork. Background discovery may add alternatives later.
	ImagesAuthoritative bool
	Versions            []Version
	Markers             []Marker
	Extras              []Extra
}

type ItemProgress

type ItemProgress interface {
	ReportItemProgress(context.Context, SessionAccess, core.RatingKey, Timeline) error
}

ItemProgress records a Jellyfin or Emby timeline when the client play session is not one the broker opened. Infuse generates PlaySessionId and still reports the item and its file-shaped MediaSourceId.

type ItemQuery

type ItemQuery struct {
	// AdjacentTo selects the anchor and its immediately neighboring visible items.
	AdjacentTo core.RatingKey
	// StartAt selects an inclusive starting item after authorization, filtering
	// and ordering. Offset and Limit apply to the resulting suffix. It cannot
	// be combined with AdjacentTo; an absent or filtered anchor is not found.
	StartAt       core.RatingKey
	Offset, Limit int
	Sort          core.SortOrder
	Desc          bool
	Types         []core.MediaType
	Recursive     bool
	Season        *int // Optional presented season number.
	Filter        core.Filter
	Watched       *bool
	Favorite      *bool
}

func SeriesNextUpQuery

func SeriesNextUpQuery() ItemQuery

SeriesNextUpQuery is the bounded children request for one series' episodes.

type ItemRequest

type ItemRequest struct {
	Viewer *core.Viewer
	Device core.Device
	Key    core.RatingKey
}

type LANLazyStreams

type LANLazyStreams interface {
	IssueLAN(context.Context, *http.Request, PlanRequest) (string, error)
	ServeHTTP(http.ResponseWriter, *http.Request)
}

LANLazyStreams issues a capability only for the currently selected DLNA viewer and verified network peer. The host derives the viewer and device; callers cannot assert either identity. Every use revalidates both.

type LastPlayedSourceReader

type LastPlayedSourceReader interface {
	LastPlayedSource(context.Context, *Viewer, Device, RatingKey) (*PlaybackSourceHistory, error)
}

LastPlayedSourceReader returns source facts only after current item policy authorization. Nil means no trustworthy source facts are available. Facts describe the last durably recorded accepted sample; they can lag playback when asynchronous persistence fails and do not describe the current source.

type LatestItem

type LatestItem struct {
	Title   Title
	AddedAt *time.Time
}

LatestItem carries date added. For a grouped series that is the latest aired episode. Nil means unknown. It is not a catalogue insertion time.

type LazyHLSStreams

type LazyHLSStreams interface {
	IssueHLS(context.Context, string, PlanRequest, StreamRequest) (string, error)
}

LazyHLSStreams issues an HLS master capability without opening a session. All playlist and segment requests remain under that capability and are reauthorized by the broker. IssueHLS alone is not an eligibility check; advertise it only when a resolved PlayPlan reports HLS. Capacity and the current source and policy are checked again when playback starts.

type LazyStreams

type LazyStreams interface {
	Issue(context.Context, string, PlanRequest) (string, error)
	ServeHTTP(http.ResponseWriter, *http.Request)
}

LazyStreams issues reusable, short-lived playback capabilities without opening a playback session. The issuing credential never appears in the returned URL.

type LibraryActivity

type LibraryActivity interface {
	LatestAdded(context.Context, *Viewer, Device, string, int) ([]LatestItem, error)
	// requireExact requests a complete filtered count; an implementation must
	// return an error if it cannot determine one within its resource bounds.
	Resume(context.Context, *Viewer, Device, string, []MediaType, int, int, bool) (ActivityPage, error)
}

LibraryActivity provides home-independent library and watch-state queries. LatestAdded returns movie/show library roots; TV defaults to grouped series.

type LibraryActivityGrouping

type LibraryActivityGrouping interface {
	LatestAddedGrouped(context.Context, *Viewer, Device, string, int, bool) ([]LatestItem, error)
}

LibraryActivityGrouping selects grouped series or individual aired episodes.

type LibraryCollageSource

type LibraryCollageSource interface {
	LibraryCollage(context.Context, *Viewer, Device, string) (Image, error)
}

LibraryCollageSource builds that collage for one library view. viewID is the view GUID. A change in the child posters produces a different image.

type LineupStreams

type LineupStreams interface {
	IssueLineup(context.Context, string, PlanRequest) (string, error)
}

LineupStreams issues a reusable, media-only lineup capability. The issuer revalidates the source grant and channel policy on every media request. The returned /sessions/lineup/<token>/ prefix is followed by a canonical base64url channel ID and /live/index.m3u8.

type ListenerSpec

type ListenerSpec struct {
	Address    string `json:"address"`
	PathPrefix string `json:"pathPrefix,omitempty"`
	TLS        bool   `json:"tls"`
	// Shared means the app supplies this listener; the manager must not bind it.
	Shared bool `json:"shared,omitempty"`
}

type LiveChannel

type LiveChannel struct {

LiveChannel contains public metadata and a neutral channel identifier. It never contains IPTV source URLs or credentials.

type LiveGuideQuery

type LiveGuideQuery struct {
	Channels    []string
	From, Until time.Time
	Limit       int
	Device      core.Device
}

type LiveProgramme

type LiveProgramme struct {
	ID, ChannelID                   string
	Start, End                      time.Time
	Item                            core.RatingKey
	Title, Summary, Rating, Artwork string
	ShowTitle, EpisodeTitle         string
	Season, Episode                 int
	Images                          []Image
}

type LiveTV

type LiveTV interface {
	Channels(context.Context, *core.Viewer) ([]LiveChannel, error)
	Guide(context.Context, *core.Viewer, LiveGuideQuery) ([]LiveProgramme, error)
	ResolveChannelGUID(context.Context, *core.Viewer, string) (LiveChannel, error)
	ResolveProgrammeGUID(context.Context, *core.Viewer, string, LiveGuideQuery) (LiveProgramme, error)
}

LiveTV applies the same per-viewer access and safety policy as Plex Live TV. Viewer must be from the authenticated session. GUID resolution never returns channels or programmes that the viewer is not permitted to see.

type Marker

type Marker struct {
	Type       string
	Start, End time.Duration
}

type MediaInfo

type MediaInfo = core.MediaInfo

type MediaType

type MediaType = core.MediaType

type Membership

type Membership struct {
	Present bool
	AddedAt *time.Time
}

Membership reports an authorized title's presence and recorded addition time. AddedAt is when this viewer stored the membership. It is not the title's date added, and it is nil when no genuine stored time is known.

type MembershipReader

type MembershipReader interface {
	FavoriteItem(context.Context, *Viewer, Device, RatingKey) (Membership, error)
	WatchlistItem(context.Context, *Viewer, Device, RatingKey) (Membership, error)
}

MembershipReader reads one policy-authorized title at a time. An absent membership is distinct from an inaccessible title or inactive viewer.

type NotInterestedEntry

type NotInterestedEntry struct {
	Key     core.RatingKey
	AddedAt time.Time
}

type NotInterestedPage

type NotInterestedPage struct {
	Items []NotInterestedEntry
	Total int
}

type OpenRequest

type OpenRequest struct {
	Protocol Protocol
	PlanID   string
	Viewer   *core.Viewer
	Device   core.Device
}

type Page

type Page = core.Page

type PageArtwork

type PageArtwork interface {
	ListPage(context.Context, *core.Viewer, core.Device, []core.Title) (map[core.RatingKey][]Image, error)
}

PageArtwork lists artwork for titles the caller already loaded.

type PageFreshness

type PageFreshness struct {
	Catalog, Config, Watch, Favorite, Hidden, Listed, Images, Grants, Accounts, Safety uint64
	ArtBucket                                                                          int64
}

PageFreshness is every input of a cached browse response. A change drops the cached body. ArtBucket rotates image grants before they expire.

type PageQuery

type PageQuery struct{ Offset, Limit int }

PageQuery defaults nonpositive Limit to 50 and caps it at 500.

type PartyActor

type PartyActor struct {
	Viewer   *core.Viewer
	Device   core.Device
	Protocol Protocol
}

PartyActor is one device of one viewer on one protocol. The same viewer on Silo and Jellyfin is two actors, so both can sit in one party.

type PartyCommand

type PartyCommand struct {
	ID, Action, Jellyfin, PlaylistItemID, SessionID string
	Position                                        time.Duration
	ExecuteAt, IssuedAt                             time.Time
	Playback                                        string
	SelectionRevision                               int64
	Rate                                            float64
}

PartyCommand is a scheduled transport change. Position is the playhead at ExecuteAt. Clients wait until that server time, which absorbs their latency.

type PartyCreate

type PartyCreate struct {
	RoomID, Mode, Name string
}

PartyCreate opens a room. RoomID may be empty; the engine mints a UUID. Mode is host_pick. Vote is refused until suggestion voting exists.

type PartyEvent

type PartyEvent struct {
	Type                 string
	View                 PartyView
	Command              PartyCommand
	GroupKind            string
	GroupData            any
	Reason               string
	ClientSent, Received time.Time
	Sent                 time.Time
	ErrorCode            string
	ErrorMessage         string
}

PartyEvent is one message for one member's socket.

type PartyInput

type PartyInput struct {
	Action   string
	Position time.Duration
	Rate     float64
}

PartyInput is a play, pause, or seek. Rate 0 leaves the room rate unchanged.

type PartyJoin

type PartyJoin struct {
	Code, Token, GroupID string
}

PartyJoin accepts a Silo code, a Silo invite token, or a Jellyfin group id.

type PartyMember

type PartyMember struct {
	ViewerID                                       int64
	Name                                           string
	Protocol                                       Protocol
	DeviceID                                       string
	Host, Self, Connected, Ready, Buffering, Lobby bool
	IgnoreWait, Blocked                            bool
}

PartyMember is one couch in the room, as seen by a particular actor.

type PartyPick

type PartyPick struct {
	Item              core.RatingKey
	FileID, LibraryID string
}

PartyPick is the title the room will play. File and library are Silo hints. Each member still opens their own broker session for that title.

type PartyQueue

type PartyQueue struct {
	Kind            string
	Items           []core.RatingKey
	Index           int
	PlaylistItemID  string
	Position        time.Duration
	Repeat, Shuffle string
}

PartyQueue is a Jellyfin playlist edit. Replace also arms playback.

type PartyQueueItem

type PartyQueueItem struct {
	Item           core.RatingKey
	ContentID      string
	PlaylistItemID string
}

PartyQueueItem is one title in the shared queue.

type PartyReport

type PartyReport struct {
	Kind                           string
	SessionID, CommandID, Playlist string
	Position                       time.Duration
	Rate                           float64
	Paused, Ready, Lobby, Ignore   *bool
	ClientSent, When               time.Time
	Playing                        bool
}

PartyReport is a realtime membership update from either dialect.

type PartySocket

type PartySocket struct {
	Actor  PartyActor
	Events <-chan PartyEvent
	Close  func()
}

PartySocket is the live Silo room connection.

type PartyTicket

type PartyTicket struct {
	Ticket                string
	ExpiresIn, MaxSeconds int
	Protocol              string
}

PartyTicket is a single-use Silo socket credential.

type PartyView

type PartyView struct {
	RoomID, Code, JoinToken, RoomToken, InvitePath, Name string
	Phase, Playback, SelectionMode, GuestPolicy, Role    string
	SelectionRevision, Generation                        int64
	Item                                                 core.RatingKey
	ContentID, FileID, LibraryID                         string
	Paused                                               bool
	Position                                             time.Duration
	AnchorAt                                             time.Time
	Rate                                                 float64
	HostConnected                                        bool
	CanTransport, CanManage, IgnoreWait                  bool
	AttachedSessionID                                    string
	Members                                              []PartyMember
	Repeat, Shuffle                                      string
	Queue                                                []PartyQueueItem
	QueueIndex                                           int
	UpdatedAt                                            time.Time
}

PartyView is the room as one member is allowed to see it.

type PeopleImageReader

type PeopleImageReader interface {
	AuthorizePersonImage(context.Context, *Viewer, Device, RatingKey, Image, func(context.Context) error) error
}

PeopleImageReader checks exact portrait ownership and current credit policy in one host-owned snapshot. Generic ItemArtwork is not a substitute. The optional trusted admission callback must not publish; it runs after the exact descriptor match, before final policy validation and lease release.

type PeopleQuery

type PeopleQuery struct {
	Query string
	Limit int
	Scope PeopleScope
}

type PeopleReader

type PeopleReader interface {
	People(context.Context, *Viewer, Device, PeopleQuery) ([]PersonDetail, error)
	Person(context.Context, *Viewer, Device, string, PersonReadOptions) (PersonDetail, error)
	// PersonCredit checks one current cached title-credit membership.
	PersonCredit(context.Context, *Viewer, Device, RatingKey, int64) (PersonDetail, error)
}

PeopleReader resolves existing person facet IDs through current visible credit membership, including episode-only credits. Reads never resolve media sources. Prefetch must not schedule a provider refresh.

type PeopleScope

type PeopleScope string
const (
	PeopleAll               PeopleScope = ""
	PeopleVideo             PeopleScope = "video"
	PeopleVideoWithEpisodes PeopleScope = "video_with_episodes"
	PeopleMovies            PeopleScope = "movie"
	PeopleSeries            PeopleScope = "series"
	PeopleEpisodes          PeopleScope = "episode"
)

type Person

type Person = core.Person

type PersonArtwork

type PersonArtwork interface {
	PersonImages(context.Context, ArtworkRequest, Title) ([]Image, error)
}

PersonArtwork constructs known portrait descriptors only from the detached current title supplied by a host's authorized credit snapshot. It performs no metadata lookup, refresh, scheduling, or independent title-cache read.

type PersonDetail

type PersonDetail struct {
	ID, Name, IMDB string
	TMDB           int64
	ArtworkItem    RatingKey
	Images         []Image
}

PersonDetail contains only facts from currently visible credits. Artwork is optional and remains bound to the authorized title that owns the image.

type PersonReadOptions

type PersonReadOptions struct{ Prefetch bool }

type PersonalHomeStore

type PersonalHomeStore interface {
	LoadPersonalHome(ctx context.Context, protocol string, viewerID int64, config string) ([]byte, error)
	SavePersonalHome(ctx context.Context, protocol string, viewerID int64, config string, body []byte) error
	PersonalHomeViewers(ctx context.Context) ([]core.User, error)
}

PersonalHomeStore persists one viewer's personalized library list. The body is an opaque JSON document owned by the Media Browser frontend.

type Placement

type Placement string

Placement identifies where rows are rendered.

const (
	PlacementHome    Placement = "home"
	PlacementLibrary Placement = "library"
	PlacementDetail  Placement = "detail"
)

type PlanRequest

type PlanRequest struct {
	// Version is a resolver-issued variant ID in legacy mode, or a scoped
	// VersionHandles handle when ExactVersion is set. Empty selects automatically.
	Version string
	// ResolvedRelease is the release id just returned by VersionHandles.Resolve
	// for Version, in this process. Plan checks that the handle row still names
	// that release and does not list offers again. Callers that did not resolve
	// leave it empty, and Plan validates the offer itself.
	ResolvedRelease string
	// ExpectedSourceETag binds playback to a previously offered resolved source.
	// It is not an authorization credential. A missing or changed source fails
	// closed instead of resolving a different release.
	ExpectedSourceETag string
	// DetailSource is an opaque, scoped handle returned by DetailPlan.
	DetailSource string
	Viewer       *core.Viewer
	Device       core.Device
	Protocol     Protocol
	Item         core.RatingKey
	// Channel is the stable Host.LiveTV channel ID. Exactly one of Item and
	// Channel must be supplied.
	Channel string
	Caps    core.ClientCaps
	Intent  PlayIntent
}

type PlayIntent

type PlayIntent struct {
	Estimate bool
	Options  core.DecideOptions
	// ExactVersion treats PlanRequest.Version as a scoped opaque handle and
	// refuses any substitute release, including during later source failover.
	ExactVersion bool
	// Set flags distinguish omitted choices from stream index zero and
	// an explicit subtitle-off choice (SubtitleStream == -1).
	AudioSet    bool
	SubtitleSet bool
	// AudioOrdinal selects a zero-based audio-only position from the opened,
	// probed source. SubtitleStreamIndex is an absolute source stream index;
	// -1 explicitly disables subtitles. Nil preserves normal preferences.
	AudioOrdinal        *int
	SubtitleStreamIndex *int
	Position            time.Duration
	ClientSessionID     string
	PlaybackID          string
	// AllowTranscoding is nil for the existing default; false forbids video
	// or audio transcoding while retaining any allowed direct-stream remux.
	AllowTranscoding *bool
	// PreferRemux asks for a copy-only remux when source changes would
	// otherwise disrupt the client. The broker still decides whether it applies.
	PreferRemux bool
	Plex        *PlexHints
}

type PlayPlan

type PlayPlan struct {
	ID        string
	Estimated bool
	Media     core.MediaInfo
	Decision  core.Decision
	// Alternatives are evaluated against this same source and client policy.
	// DirectStream denotes copy-only remux, without encoding either stream.
	DirectPlay, DirectStream, Transcoding bool
	// HLS reports whether this resolved source can be delivered as HLS under
	// the declared client profile. Encoder capacity is checked at stream start.
	HLS bool
	// HLSContainer is the authoritative segment container from the resolved HLS
	// output decision (mpegts, fmp4, or mkv). Empty means unknown or ineligible;
	// it is not the source container or an encoder-capacity reservation.
	HLSContainer string
	// ETag identifies the resolved immutable source when available; it is
	// empty when the backend cannot prove a stable source identity.
	ETag string
	// DetailSource is a scoped, expiring handle for the resolved source.
	DetailSource string
}

type PlaybackSourceHistory

type PlaybackSourceHistory = core.PlaybackSourceHistory

type Playlist

type Playlist = core.Playlist

type PlaylistLibrary

type PlaylistLibrary interface {
	Playlists(context.Context, *core.Viewer, PageQuery) (PlaylistPage, error)
	CreatePlaylist(context.Context, *core.Viewer, string, []core.RatingKey) (*core.Playlist, error)
	AddPlaylistItems(context.Context, *core.Viewer, core.RatingKey, []core.RatingKey) error
	RemovePlaylistItem(context.Context, *core.Viewer, core.RatingKey, int) error
	MovePlaylistItem(context.Context, *core.Viewer, core.RatingKey, int, int) error
	DeletePlaylist(context.Context, *core.Viewer, core.RatingKey) error
}

PlaylistLibrary is the viewer's playlists. Remove and move indexes are positions in the visible item list, never raw storage positions that include titles hidden from this viewer.

type PlaylistPage

type PlaylistPage struct {
	Items []core.Playlist
	Total int
}

PlaylistPage is one viewer's own playlists. Item keys are titles that viewer is allowed to see, in playlist order.

type PlexHints

type PlexHints struct {
	Collection        string
	MediaIndex        int
	PartReleaseID     string
	AudioSelection    int
	SubtitleSelection int
	SubtitleSet       bool
	SubtitleStream    *core.StreamInfo
}

PlexHints carries Plex-specific selections that cannot be represented by neutral stream indexes. Only the Plex adapter should populate it.

type Preferences

Preferences stores presentation state for the bound surface. Viewer must be obtained from the current authenticated session. These values are not policy.

type ProgressSample

type ProgressSample struct {
	InstallationID  string
	Sequence        uint64
	PositionSeconds float64
	Paused          bool
	// Stop finalizes playback under the same ownership gate as sample ordering.
	Stop bool
}

ProgressSample is the exact Silo v2 sample before conversion to duration. InstallationID is the server installation identity, not the device ID.

type Protocol

type Protocol = core.Protocol

Protocol identifies a surface independently of client product or platform.

type PublicViewer

type PublicViewer struct {
	ID   int64
	Name string
	// HasConfiguredPassword is known only when the identity service can
	// establish it from its active local credential record.
	HasConfiguredPassword *bool
}

PublicViewer is the minimal identifier displayed by an owner-enabled picker.

type QuickConnectDetails

type QuickConnectDetails struct {
	Approved     bool
	Code, Secret string
	Device       core.Device
	CreatedAt    time.Time
	ExpiresAt    time.Time
}

QuickConnectDetails is returned only to the holder of the polling secret.

type RatingKey

type RatingKey = core.RatingKey

func ExtraKey

func ExtraKey(id int64) RatingKey

func MovieKey

func MovieKey(tmdb int64) RatingKey

func SeasonKey

func SeasonKey(show int64, season int) RatingKey

func ShowKey

func ShowKey(tmdb int64) RatingKey

type Registry

type Registry struct {
	// contains filtered or unexported fields
}

Registry serializes lifecycle transitions so a protocol has at most one live instance. The host factory must bind identity to the requested surface.

func NewRegistry

func NewRegistry(host func(Protocol) Host) *Registry

func (*Registry) Descriptors

func (r *Registry) Descriptors() []Descriptor

func (*Registry) Instance

func (r *Registry) Instance(id Protocol) (Instance, bool)

func (*Registry) Mount

func (r *Registry) Mount(ctx context.Context, id Protocol) (Instance, error)

func (*Registry) Register

func (r *Registry) Register(f Frontend) error

func (*Registry) Unmount

func (r *Registry) Unmount(ctx context.Context, id Protocol) error

func (*Registry) ValidateSettings

func (r *Registry) ValidateSettings(id Protocol, settings Settings) (bool, error)

ValidateSettings delegates protocol-specific settings to the registered frontend. The bool reports whether it provides a validator.

type RelatedArtwork

type RelatedArtwork struct {
	People              []Image
	PeopleAuthoritative bool
	Season, Series      *ArtworkOwner
}

RelatedArtwork contains only artwork associated with an authorized item. Season is the episode's canonical season; Series is its show. People belong to the requested item, and Image.Subject identifies each credited person.

type RelatedArtworkProvider

type RelatedArtworkProvider interface {
	RelatedArtwork(context.Context, *Viewer, Device, RatingKey) (RelatedArtwork, error)
}

RelatedArtworkProvider supplies cache-only parent and credit artwork. Each descriptor must be granted using its owning item, and is revalidated by the image-grant service on issue and read.

type ReportOutcome

type ReportOutcome string
const (
	ReportApplied  ReportOutcome = "applied"
	ReportReplayed ReportOutcome = "replayed"
	ReportStale    ReportOutcome = "stale_sample"
	ReportConflict ReportOutcome = "conflict"
)

type RequestMemo

type RequestMemo struct {
	Mu      sync.Mutex
	Viewer  *core.User
	Visible map[core.RatingKey]bool
	Aired   map[core.RatingKey]AiredMemo
}

RequestMemo keeps one viewer snapshot and one visibility decision per title for the rest of a single request.

func RequestMemoFrom

func RequestMemoFrom(ctx context.Context) *RequestMemo

RequestMemoFrom returns the memo installed by WithRequestMemo.

type ResolvedEventSubject

type ResolvedEventSubject struct {
	Ref           FavoriteRef
	PersonFacetID string
	Favorite      bool
	UserData      *core.WatchStatus
}

ResolvedEventSubject is viewer-authorized current data for an event entity. PersonFacetID shares the namespace used by person facets.

type RouteSource

type RouteSource interface{ Routes() []conform.Route }

RouteSource exposes the exact routes registered by a mounted frontend. A missing implementation means inventory is unavailable, not empty.

type Row

type Row struct {
	ID, Title    string
	Purpose      RowPurpose
	Kind         string // Stable semantic producer kind, independent of protocol.
	Layout       RowLayout
	Style        string
	Promoted     bool
	Rank         int
	ImpressionID string
	// Handle is a server-issued row interaction capability.
	Handle string
	// Entries is the ordered heterogeneous row; Items remains for compatibility.
	Entries    []RowEntry
	Items      []core.Title
	More       bool
	Collection core.RatingKey
}

type RowDirectory

type RowDirectory struct {
	ID, Title, Description, Image string
	Kind                          string
}

RowDirectory identifies a browsable destination in the experience.

type RowEntry

type RowEntry struct {
	Kind        RowEntryKind
	Handle      string
	Title       *core.Title
	Collection  *core.Collection
	Playlist    *core.Playlist
	LiveChannel *RowLiveChannel
	Directory   *RowDirectory
}

RowEntry is a tagged union: Kind identifies the one non-nil payload. Handle is an opaque, server-issued interaction capability scoped to the viewer and device; it is not an account credential.

type RowEntryKind

type RowEntryKind string

RowEntryKind identifies a neutral entry independently of wire formats.

const (
	RowEntryTitle       RowEntryKind = "title"
	RowEntryCollection  RowEntryKind = "collection"
	RowEntryPlaylist    RowEntryKind = "playlist"
	RowEntryLiveChannel RowEntryKind = "liveChannel"
	RowEntryDirectory   RowEntryKind = "directory"
)

type RowInteraction

type RowInteraction struct {
	Viewer   *core.Viewer
	Device   core.Device
	Protocol Protocol
	Handle   string
	Kind     RowInteractionKind
}

type RowInteractionKind

type RowInteractionKind string

RowInteractionKind is a viewer action on an issued row or entry.

const (
	RowImpression RowInteractionKind = "impression"
	RowClick      RowInteractionKind = "click"
	RowPlay       RowInteractionKind = "play"
)

type RowInteractionReporter

type RowInteractionReporter interface {
	ReportRowInteraction(context.Context, RowInteraction) error
}

RowInteractionReporter validates issued handles, membership and device scope before recording actions. Clients must never construct handles or contexts.

type RowLayout

type RowLayout struct {
	Order int
	Style string
	Paint RowPaint
}

RowLayout describes Home Designer presentation selected by experience.

type RowLiveChannel

type RowLiveChannel struct {
	GuideReference         string
	Current, Next          *RowProgramme
	Images                 []Image
}

RowLiveChannel contains viewer-visible channel metadata, never source URLs.

type RowPaint

type RowPaint struct {
	Background, Foreground, Accent string
	Artwork                        string
}

RowPaint carries optional presentation colors and artwork references.

type RowProgramme

type RowProgramme struct {
	ID, Title, EpisodeTitle string
	Start, End              time.Time
	Season, Episode         int
	Item                    core.RatingKey
}

RowProgramme describes one guide entry without an upstream stream URL.

type RowPurpose

type RowPurpose = core.RowPurpose

RowPurpose describes why a row exists, independent of wire-level hub IDs.

const (
	RowContinue         RowPurpose = "continue"
	RowNextUp           RowPurpose = "nextUp"
	RowRecentlyReleased RowPurpose = "recentlyReleased"
	RowRecentlyAdded    RowPurpose = "recentlyAdded"
	RowCollection       RowPurpose = "collection"
	RowRecommendation   RowPurpose = "recommendation"
	RowLive             RowPurpose = "live"
	RowWatchlist        RowPurpose = "watchlist"
)

type RowRequest

type RowRequest struct {
	Viewer    *core.Viewer
	Device    core.Device
	Placement Placement
	ViewID    string
	Item      core.RatingKey
	Limit     int
	// Purpose asks for one row. The zero value still returns the whole placement.
	Purpose RowPurpose
}

type RowView

type RowView struct {
	ID          string
	Title, Kind string
	Purpose     RowPurpose
	Layout      RowLayout
	Rank        int
}

RowView identifies one server-owned, viewer/device/surface-scoped visit. ID binds one immutable snapshot and changes on refresh.

type RowViewPage

type RowViewPage struct {
	Entries          []RowEntry
	ImpressionHandle string
	Total            int
	TotalExact       bool
	More             bool
	// Truncated means the snapshot is a bounded prefix of the source row.
	// More only indicates entries available in this snapshot.
	Truncated bool
}

type RowViewPageRequest

type RowViewPageRequest struct {
	Viewer        *Viewer
	Device        Device
	Protocol      Protocol
	ID            string
	Offset, Limit int
	Kinds         []RowEntryKind
}

type RowViewRequest

type RowViewRequest struct {
	Viewer    *Viewer
	Device    Device
	Protocol  Protocol
	Placement Placement
	ViewID    string
	Item      RatingKey
	// Refresh starts new snapshots and invalidates earlier page generations.
	Refresh bool
}

type RowViews

type RowViews interface {
	ListRowViews(context.Context, RowViewRequest) ([]RowView, error)
	ResolveRowView(context.Context, RowViewPageRequest) (RowViewPage, error)
}

RowViews is optional; IDs are not credentials. Implementations must reauthorize each call and issue page-scoped interaction handles.

type SampleReporter

type SampleReporter interface {
	ReportSample(context.Context, SessionAccess, string, ProgressSample) (ReportOutcome, error)
}

SampleReporter reports an idempotent sample and returns its durable outcome. It is additive to Sessions.Report, whose existing semantics stay unchanged.

type ScopedMedia

type ScopedMedia interface {
	ServeMediaAccess(http.ResponseWriter, *http.Request, SessionAccess)
}

ScopedMedia serves a stream only to the authenticated device that owns it. The scoped URL's grant and current playback policy are also checked.

type ScopedTrackPreferenceService

type ScopedTrackPreferenceService interface {
	GetScoped(context.Context, *Viewer, TrackScope) (TrackPreferences, int, int, string, map[string]string, error)
	SetScoped(context.Context, *Viewer, string, string, TrackPreferencePatch) error
	DeleteScoped(context.Context, *Viewer, string, string, string) error
	SetAudio(context.Context, *Viewer, []string) error
	SetSubtitleLanguage(context.Context, *Viewer, []string) error
	SetSubtitleMode(context.Context, *Viewer, string) error
	SetAppearance(context.Context, *Viewer, json.RawMessage) error
	SetBitrate(context.Context, *Viewer, int) error
	SetHeight(context.Context, *Viewer, int, string) error
}

ScopedTrackPreferenceService is an optional extension for shared playback preferences; identifiers use the host's library and rating-key namespaces.

type SearchPage

type SearchPage struct {
	Page         core.Page
	TotalExact   bool
	Continuation Continuation
}

type Session

type Session struct {
	ID, MediaPath string
	Protocol      Protocol
	ViewerID      int64
	// ClientSessionID is a non-secret protocol installation/session identifier.
	ClientSessionID string
	Device          core.Device
	Item            core.RatingKey
	Channel         string
	Media           *core.MediaInfo
	StartedAt       time.Time
	Capabilities    *SessionCapabilities
}

type SessionAccess

type SessionAccess struct {
	Viewer   *core.Viewer
	Device   core.Device
	Protocol Protocol
	Owner    bool
}

SessionAccess binds client operations to an authenticated viewer and surface. Owner requests owner scope; it is not proof of authorization. The broker verifies the authenticated viewer is an active owner.

type SessionBusyError

type SessionBusyError struct{ RetryAfter time.Duration }

func (*SessionBusyError) Error

func (*SessionBusyError) Error() string

func (*SessionBusyError) Is

func (*SessionBusyError) Is(target error) bool

type SessionCapabilities

type SessionCapabilities struct {
	PlayableMediaTypes           []string
	SupportedCommands            []string
	SupportsMediaControl         *bool
	SupportsPersistentIdentifier *bool
	SupportsRemoteControl        *bool
	DeviceProfile                json.RawMessage
	AppStoreURL                  string
	IconURL                      string
}

SessionCapabilities are declared by an authenticated device on one surface. URL fields are metadata and must never be fetched by the broker.

type SessionMarkers

type SessionMarkers struct {
	Known      bool
	SourceETag string
	Markers    []Marker
}

SessionMarkers describes only a complete set bound to the current source. Known=false means the source has not established a complete marker set.

type Sessions

type Sessions interface {
	Plan(context.Context, PlanRequest) (PlayPlan, error)
	Open(context.Context, OpenRequest) (Session, error)
	// StartStream revalidates access to the session and returns its scoped URL.
	StartStream(context.Context, SessionAccess, string, StreamRequest) (string, error)
	// SubtitleURL returns a scoped URL for a subtitle stream index and format.
	SubtitleURL(context.Context, SessionAccess, string, int, string) (string, error)
	// Markers returns source-bound ranges for the authorized playback session.
	Markers(context.Context, SessionAccess, string) (SessionMarkers, error)
	// ServeMedia authorizes the scoped grant and serves direct, HLS or DASH data.
	ServeMedia(http.ResponseWriter, *http.Request)
	Report(context.Context, SessionAccess, string, Timeline) error
	Stop(context.Context, SessionAccess, string) error
	Command(context.Context, *core.Viewer, string, Command) error
	UpdateCapabilities(context.Context, SessionAccess, SessionCapabilities) error
	Capabilities(context.Context, SessionAccess) (SessionCapabilities, error)
	Sessions(context.Context, SessionAccess) ([]Session, error)
	Recover(context.Context, string, string, time.Duration) error
	TranscodeFor(context.Context, string) (core.HLSSession, bool)
	// Events includes events from all cluster nodes, filters by viewer unless owner access is authorized, and ends on cancellation.
	Events(context.Context, EventScope) (<-chan Event, error)
}

Sessions owns playback across protocols. Open revalidates the broker-owned plan, protocol, viewer, device and admission; estimated plans cannot be opened. MediaPath is scoped and unguessable and never contains account credentials.

type Settings

type Settings map[string]any

type SettingsValidator

type SettingsValidator interface{ ValidateSettings(Settings) error }

SettingsValidator lets a frontend validate its own protocol-specific options. The host also checks common listener options before persistence.

type SortOrder

type SortOrder = core.SortOrder

type SourceOffer

type SourceOffer struct {
	ID        string
	ExpiresAt time.Time
	Target    SourceOfferTarget
}

type SourceOfferTarget

type SourceOfferTarget struct {
	Item          RatingKey
	VersionHandle string
	DetailSource  string
	ETag          string
}

SourceOfferTarget contains one exact scoped selector, never an upstream ID. A resolved detail selector also carries its immutable source revision.

type SourceOffers

SourceOffers maps scoped selectors to bounded, expiring numeric protocol IDs. IDs are never credentials and must be resolved under current viewer policy.

type Status

type Status struct {
	Mounted          bool     `json:"mounted"`
	Addresses        []string `json:"addresses"`
	ConnectURLs      []string `json:"connectUrls,omitempty"`
	LAN              string   `json:"lan"`
	WAN              string   `json:"wan"`
	Clients24h       int      `json:"clients24h"`
	Clients24hKnown  bool     `json:"clients24hKnown"`
	LiveStreams      int      `json:"liveStreams"`
	LiveStreamsKnown bool     `json:"liveStreamsKnown"`
	TargetVersion    string   `json:"targetVersion"`
	Conformance      string   `json:"conformance"`
	Error            string   `json:"error,omitempty"`
	Warnings         []string `json:"warnings,omitempty"`
}

type StreamFormat

type StreamFormat string
const (
	StreamDirect StreamFormat = "direct"
	StreamHLS    StreamFormat = "hls"
	StreamDASH   StreamFormat = "dash"
	StreamHTTP   StreamFormat = "http"
)

type StreamInfo

type StreamInfo = core.StreamInfo

type StreamRequest

type StreamRequest struct {
	Format          StreamFormat
	Position        time.Duration
	SegmentDuration time.Duration
}

StreamRequest describes output, not an upstream URL or credential. The broker owns the input, decision and stream grant.

type Subscriber

type Subscriber interface {
	Subscribe(context.Context, EventScope) (<-chan Event, error)
}

Subscriber delivers events across nodes until the context is cancelled.

type SubtitleCatalog

type SubtitleCatalog interface {
	Enabled() bool
	Search(context.Context, *core.Viewer, core.Device, core.RatingKey, string) ([]SubtitleOffer, error)
	Download(context.Context, *core.Viewer, core.Device, core.RatingKey, string) (int, error)
}

SubtitleCatalog searches and downloads sidecars. Download fetches only an offer Search returned for that title. It does not prefetch.

type SubtitleOffer

type SubtitleOffer struct {
	ID, Language, Name, Provider, Format, Author     string
	Downloads                                        int
	Rating                                           float64
	HearingImpaired, Forced, HashMatch, AITranslated bool
}

SubtitleOffer is one subtitle search result. ID is the only value a later Download accepts, and only for the title Search returned it for.

type SurfaceIdentity

type SurfaceIdentity interface {
	Resolve(context.Context, string) (*core.Viewer, error)
	// ViewerTimes revalidates the surface credential and allows only the same
	// viewer or an active owner to read another active viewer's timestamps.
	ViewerTimes(context.Context, string, int64) (ViewerTimes, error)
	PublicViewers(context.Context) ([]PublicViewer, error)
	SignIn(context.Context, string, string, core.Device) (string, error)
	IssueRefresh(context.Context, string, core.Device) (string, error)
	Refresh(context.Context, string, core.Device) (string, string, error)
	QuickConnectInitiate(context.Context, core.Device) (code, secret string, err error)
	QuickConnectStatus(context.Context, string) (approved bool, err error)
	QuickConnectDetails(context.Context, string) (QuickConnectDetails, error)
	QuickConnectPoll(context.Context, string) (string, error)
	QuickConnectApprove(context.Context, *core.Viewer, string) error
	Revoke(context.Context, string) error
	SetupComplete() bool
}

SurfaceIdentity is bound to one protocol by the host factory. Quick Connect approval requires a viewer obtained from a successfully authenticated session; frontends must not construct a viewer from untrusted request data.

func BindIdentity

func BindIdentity(resolver core.Identity, surface Protocol) SurfaceIdentity

BindIdentity prevents a frontend from choosing a different authentication surface.

type Ticket

type Ticket struct {
	Viewer *Viewer
	Device Device
	// SourceHash identifies the issuing grant for host-side revalidation only.
	SourceHash string
}

Ticket is a one-use, purpose-bound authorization for a realtime handshake.

type Tickets

type Tickets interface {
	Issue(context.Context, string, Device, string) (string, error)
	Consume(context.Context, string, string) (Ticket, error)
	Active(context.Context, Ticket) (bool, error)
}

type Timeline

type Timeline struct {
	// PlaybackID may be empty for clients that do not send one. The broker
	// preserves its no-ID supersession semantics.
	PlaybackID      string
	ClientSessionID string
	// Sequence is optional; zero preserves the legacy unordered behavior.
	Sequence           uint64
	Position, Duration time.Duration
	State              string
}

type Title

type Title = core.Title

func LoadSeriesNextUp

func LoadSeriesNextUp(ctx context.Context, exp Experience, viewer *Viewer, device Device, series RatingKey, resumable bool) (*Title, error)

LoadSeriesNextUp loads one series' episodes through exp.Children and selects the next episode. Children is invoked only with that series key.

func SeriesNextUp

func SeriesNextUp(eps []Title, st map[RatingKey]WatchStatus, series RatingKey, resumable bool, unavailable func(*Title) bool) *Title

SeriesNextUp selects that series' next regular episode. Specials are skipped. When resumable, an in-progress episode wins; otherwise the first unwatched episode after the last completed one is returned, or S1E1 when none are watched. Episodes of any other series are ignored.

type TrackPreferencePatch

type TrackPreferencePatch struct {
	AudioLanguages, SubtitleLanguages *[]string
	SubtitleMode                      *string
	SubtitleAppearance                *json.RawMessage
	MaxBitrateKbps                    *int
	MaxHeight                         *int
	PreferredQuality                  *string
}

type TrackPreferenceService

type TrackPreferenceService interface {
	Get(context.Context, *Viewer) (TrackPreferences, error)
	SetSubtitle(context.Context, *Viewer, []string, string) error
}

type TrackPreferences

type TrackPreferences struct {
	AudioLanguages, SubtitleLanguages []string
	SubtitleMode                      string
	PreferOriginal                    bool
	SubtitleAppearance                json.RawMessage
}

type TrackScope

type TrackScope struct{ Device, Series, Library string }

type TranscodeCapacityError

type TranscodeCapacityError struct {
	RetryAfter time.Duration
	Cause      error
}

TranscodeCapacityError carries a suggested retry delay. Capacity is checked atomically at stream start and is not reserved by an earlier Plan.

func (*TranscodeCapacityError) Error

func (e *TranscodeCapacityError) Error() string

func (*TranscodeCapacityError) Is

func (e *TranscodeCapacityError) Is(target error) bool

func (*TranscodeCapacityError) Unwrap

func (e *TranscodeCapacityError) Unwrap() error

type TrickplayOffer

type TrickplayOffer struct {
	Width, Height int
	Columns, Rows int
	Count         int
	Interval      time.Duration
	Bandwidth     int
}

TrickplayOffer is Jellyfin sprite geometry for one generated width. Width and Height are one thumbnail in pixels. Columns and Rows are the grid inside each sheet. Interval is the time between thumbnails.

type TrickplayTiles

type TrickplayTiles interface {
	TrickplayOffer(context.Context, SessionAccess, core.RatingKey) (TrickplayOffer, bool)
	TrickplaySheet(context.Context, SessionAccess, core.RatingKey, int) ([]byte, error)
}

TrickplayTiles serves preview sheets for an item the viewer may play. The broker owns release identity and generation. A false offer means no frame exists yet, which clients render as an empty trickplay map.

type Version

type Version struct {
	ID, Name string
	// Edition is the release's named cut when the catalogue recorded one.
	Edition string
	// AddedAt follows date added. Movies and episodes use their own release
	// or air date. Series and seasons use the latest aired episode, then
	// the premiere. It is not a catalogue insertion, observation, or refresh.
	AddedAt time.Time
	Media   core.MediaInfo
	// Markers are ranges for this version's probed timeline. Nil means the
	// version has no separate timeline yet; a detail-level marker set is not
	// a substitute when several files are present.
	Markers []Marker
	// Source facts are absent unless they are known for this version. FileName
	// is a basename only; DateModified is never a catalogue fallback date.
	FileName     string     `json:"fileName,omitempty"`
	PartCount    *int       `json:"partCount,omitempty"`
	ETag         string     `json:"etag,omitempty"`
	DateModified *time.Time `json:"dateModified,omitempty"`
	PublishedAt  *time.Time `json:"publishedAt,omitempty"`
	// FirstObservedAt is the first committed observation of this candidate offer.
	// Nil means that no trustworthy observation was recorded.
	FirstObservedAt *time.Time `json:"firstObservedAt,omitempty"`
}

type VersionHandleBatch

type VersionHandleBatch interface {
	IssueBatch(context.Context, VersionScope, core.RatingKey, []string) (map[string]string, error)
}

VersionHandleBatch is an optional bounded batch capability. It validates the whole requested offer set once and issues all handles atomically.

type VersionHandles

type VersionHandles interface {
	Issue(context.Context, VersionScope, core.RatingKey, string) (string, error)
	Resolve(context.Context, VersionScope, string) (VersionTarget, error)
	// MatchSession verifies that a scoped handle denotes the source bound to
	// this authenticated local playback session.
	MatchSession(context.Context, VersionScope, string, string) error
}

type VersionScope

type VersionScope struct {
	Viewer   *core.Viewer
	Device   core.Device
	Protocol Protocol
	Caps     core.ClientCaps
}

VersionScope binds a version handle to an authenticated viewer, surface, device and host-built client capabilities. It grants no playback by itself.

type VersionTarget

type VersionTarget struct {
	Item core.RatingKey
	// Release is the candidate id stored with the handle. Empty when the
	// handle was resolved by an older caller that only needed the parent.
	Release string
}

VersionTarget is the authorized parent associated with an opaque handle. A caller must still open playback and revalidate the selected source.

type VersionedPreferences

type VersionedPreferences interface {
	GetVersioned(context.Context, *core.Viewer, string, string) (json.RawMessage, int64, time.Time, error)
	PutVersioned(context.Context, *core.Viewer, string, string, json.RawMessage) (int64, time.Time, error)
}

VersionedPreferences provides cluster-safe per-record revisions for wire contracts that require a revision to advance on every write.

type View

type View struct {
	ID   string
	Name string
	Type core.MediaType
	// Virtual is true only when the host asserts this library has no physical
	// locations. False means the host did not assert virtual origin.
	Virtual bool
}

type Viewer

type Viewer = core.Viewer

Protocol adapters use these aliases to exchange host values without importing domain packages directly. Their implementations remain owned by core.

type ViewerCapabilities

type ViewerCapabilities struct {
	IsOwner           *bool     `json:"isOwner,omitempty"`
	CanPlayRemote     *bool     `json:"canPlayRemote,omitempty"`
	CanPlay           *bool     `json:"canPlay,omitempty"`
	RemoteBitrateKbps *int      `json:"remoteBitrateKbps,omitempty"`
	CanTranscode      *bool     `json:"canTranscode,omitempty"`
	CanTranscodeAudio *bool     `json:"canTranscodeAudio,omitempty"`
	CanTranscodeVideo *bool     `json:"canTranscodeVideo,omitempty"`
	CanRemux          *bool     `json:"canRemux,omitempty"`
	CanUseLiveTV      *bool     `json:"canUseLiveTV,omitempty"`
	CanManageLiveTV   *bool     `json:"canManageLiveTV,omitempty"`
	HasLocalPassword  *bool     `json:"hasLocalPassword,omitempty"`
	AllowedLibraries  *[]View   `json:"allowedLibraries,omitempty"`
	MaxRating         *string   `json:"maxRating,omitempty"`
	CanDownload       *bool     `json:"canDownload,omitempty"`
	MaxActiveSessions *int      `json:"maxActiveSessions,omitempty"`
	BlockedTags       *[]string `json:"blockedTags,omitempty"`
	PeerRemote        *bool     `json:"peerRemote,omitempty"`
}

ViewerCapabilities are informational only. Nil fields are unknown; all operations remain subject to their authoritative policy checks.

type ViewerCapabilitiesFunc

type ViewerCapabilitiesFunc func(context.Context, *Viewer, Device, netip.Addr) (ViewerCapabilities, error)

ViewerCapabilitiesFunc receives a verified network peer, never a client-supplied forwarding value.

type ViewerPolicy

type ViewerPolicy interface {
	SetMaxRating(context.Context, *Viewer, string) error
}

ViewerPolicy mutates household policy with host-side authorization.

type ViewerTimes

type ViewerTimes struct {
	LastLogin, LastActivity time.Time
}

ViewerTimes contains observed events; a zero time means unknown.

type VirtualPaths

type VirtualPaths interface {
	Path(context.Context, *Viewer, Device, RatingKey) (string, error)
	// Paths resolves at most 50 distinct keys (256 input entries), omitting
	// hidden or unsupported items and sharing viewer-scoped library scans.
	Paths(context.Context, *Viewer, Device, []RatingKey) (map[RatingKey]string, error)
	// Base returns the verified reachable WebDAV base URL, or an error when
	// WebDAV is disabled or unreachable for the requesting client.
	Base(context.Context, *http.Request) (string, error)
}

VirtualPaths resolves a viewer-authorized item to the same relative path used by the WebDAV tree, including stable collision disambiguation.

type WatchParty

WatchParty is the shared party engine. Silo and Jellyfin adapters translate their own protocols onto it. A nil host field means the feature is off.

type WatchStatus

type WatchStatus = core.WatchStatus

Directories

Path Synopsis
Package compactids allocates durable compact protocol identifiers.
Package compactids allocates durable compact protocol identifiers.
Package frontendtest supplies configurable fakes for protocol implementations.
Package frontendtest supplies configurable fakes for protocol implementations.
kit
authhdr
Package authhdr parses client authentication headers without exposing tokens in URLs.
Package authhdr parses client authentication headers without exposing tokens in URLs.
caps
Package caps builds neutral client capabilities from protocol profiles.
Package caps builds neutral client capabilities from protocol profiles.
conformance
Package conformance reads release-generated, embedded protocol evidence.
Package conformance reads release-generated, embedded protocol evidence.
hls
Package hls writes token-free playlists under random session paths.
Package hls writes token-free playlists under random session paths.
ids
Package ids provides stable, stateless protocol identifiers.
Package ids provides stable, stateless protocol identifiers.
images
Package images contains protocol-independent artwork helpers.
Package images contains protocol-independent artwork helpers.
language
Package language exposes the shared language-tag validation to frontends.
Package language exposes the shared language-tag validation to frontends.
libpath
Package libpath defines the shared virtual library names exposed by clients.
Package libpath defines the shared virtual library names exposed by clients.
paging
Package paging applies bounded offset/limit windows without integer overflow.
Package paging applies bounded offset/limit windows without integer overflow.
quality
Package quality exposes the transcoder's published H.264 rung targets without a frontend importing the transcoder.
Package quality exposes the transcoder's published H.264 rung targets without a frontend importing the transcoder.
route
Package route provides an enumerable case-insensitive protocol router.
Package route provides an enumerable case-insensitive protocol router.
rows
Package rows supplies helpers for rendering supported neutral row entries.
Package rows supplies helpers for rendering supported neutral row entries.
sort
Package sort translates protocol sort keys into Ether browse orders.
Package sort translates protocol sort keys into Ether browse orders.

Jump to

Keyboard shortcuts

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