Documentation
¶
Overview ¶
Package sessions owns protocol-independent playback sessions.
Index ¶
- func BindEvents(events frontend.Subscriber, protocol frontend.Protocol) frontend.Subscriber
- func BindSurface(b frontend.Sessions, protocol frontend.Protocol) frontend.Sessions
- func Decide(playback core.Playback, transcoder core.Transcoder, r DecisionRequest) (core.Decision, error)
- func Estimate(ctx context.Context, playback Estimator, viewer *core.Viewer, clientID string, ...) (core.MediaInfo, *core.PlaySession)
- func HLSDecision(dec core.Decision, allowDirect bool, reconsider func() core.Decision, ...) core.Decision
- func NewLANLazyStreams(db *sql.DB, broker *Broker, clientIP func(*http.Request) (netip.Addr, bool), ...) (frontend.LANLazyStreams, error)
- func NewLazyStreams(db *sql.DB, b *Broker, protocol frontend.Protocol, grants LazyGrants, ...) (frontend.LazyStreams, error)
- func NewSourceOffers(db *sql.DB, b *Broker, protocol frontend.Protocol) (frontend.SourceOffers, error)
- func NewVersionHandles(db *sql.DB, b *Broker, protocol frontend.Protocol) (frontend.VersionHandles, error)
- func NotifyTranscodeActivity(transcoder core.Transcoder, id, state string)
- func PlexStreamSlot(index int, info core.StreamInfo) string
- func PlexStreamsMatch(a, b core.StreamInfo) bool
- func PlexWireID(key core.RatingKey, slot string) int64
- func RecordProgress(ctx context.Context, writer ProgressWriter, viewer int64, key core.RatingKey, ...) error
- func Recover[R any](ctx context.Context, table *BindingTable[R], playback any, id, inputURL string, ...) error
- func TranscodeFor[R any](table *BindingTable[R], transcoder core.Transcoder, playID string) (core.HLSSession, bool)
- func WithPlexAdmission(ctx context.Context, admit func(context.Context) (PlexAdmission, error)) context.Context
- func WithPlexServe(ctx context.Context, remote bool, format string) context.Context
- type Binding
- type BindingTable
- func (t *BindingTable[R]) ByPlayID(PlayID string) []string
- func (t *BindingTable[R]) Claim(ID string, UserID int64, ClientID string, now time.Time) bool
- func (t *BindingTable[R]) Expire(now time.Time, ttl time.Duration) []string
- func (t *BindingTable[R]) Fail(ID string, UserID int64, ClientID string, Key core.RatingKey, err error, ...)
- func (t *BindingTable[R]) ForClient(UserID int64, ClientID string, Key core.RatingKey) []string
- func (t *BindingTable[R]) Get(ID string) (*Binding[R], bool)
- func (t *BindingTable[R]) IDs() []string
- func (t *BindingTable[R]) Put(e *Binding[R])
- func (t *BindingTable[R]) Remove(ID string)
- func (t *BindingTable[R]) TakeFailure(ID string, UserID int64, Key core.RatingKey, now time.Time) (error, bool)
- func (t *BindingTable[R]) Touch(ID string, now time.Time)
- type Broker
- func (b *Broker) BindPlexStream(_ context.Context, access frontend.SessionAccess, binding PlexStreamBinding) (int64, error)
- func (b *Broker) Capabilities(ctx context.Context, a frontend.SessionAccess) (frontend.SessionCapabilities, error)
- func (b *Broker) Close(ctx context.Context)
- func (b *Broker) Command(ctx context.Context, actor *core.Viewer, id string, cmd frontend.Command) error
- func (b *Broker) ConfirmPlexAdmission(ctx context.Context, v *core.Viewer, remote bool) (*core.Viewer, error)
- func (b *Broker) DetailPlan(ctx context.Context, req frontend.PlanRequest) (frontend.PlayPlan, error)
- func (b *Broker) EnsurePlexActivity(id string, key int)
- func (b *Broker) Events(ctx context.Context, scope frontend.EventScope) (<-chan frontend.Event, error)
- func (b *Broker) ExpirePlexActivities(now time.Time, ttl time.Duration) []PlexActivity
- func (b *Broker) HasBinding(id string) bool
- func (b *Broker) HasPlexActivity(id string) bool
- func (b *Broker) ListPlexActivities() []PlexActivity
- func (b *Broker) Markers(ctx context.Context, access frontend.SessionAccess, id string) (frontend.SessionMarkers, error)
- func (b *Broker) MatchDetailSession(ctx context.Context, scope frontend.VersionScope, handle, sessionID string) error
- func (b *Broker) NotePlexEncoder(id string, format frontend.StreamFormat, decision core.Decision, ...)
- func (b *Broker) Open(ctx context.Context, req frontend.OpenRequest) (frontend.Session, error)
- func (b *Broker) OpenPlexSidecar(ctx context.Context, access frontend.SessionAccess, receipt auth.Acceptance, ...) (io.ReadCloser, core.StreamInfo, error)
- func (b *Broker) Plan(ctx context.Context, req frontend.PlanRequest) (frontend.PlayPlan, error)
- func (b *Broker) PlexSessionForPlayback(ctx context.Context, a frontend.SessionAccess, item frontend.RatingKey, ...) (string, error)
- func (b *Broker) PlexSessionForSource(ctx context.Context, a frontend.SessionAccess, item frontend.RatingKey, ...) (string, error)
- func (b *Broker) PlexSessionSource(id string) (string, bool)
- func (b *Broker) Recover(ctx context.Context, id, url string, at time.Duration) error
- func (b *Broker) RemovePlexActivity(id string) (PlexActivity, bool)
- func (b *Broker) Report(ctx context.Context, a frontend.SessionAccess, id string, t frontend.Timeline) error
- func (b *Broker) ReportItemProgress(ctx context.Context, a frontend.SessionAccess, item core.RatingKey, ...) error
- func (b *Broker) ReportProgress(ctx context.Context, a frontend.SessionAccess, item core.RatingKey, ...) error
- func (b *Broker) ReportSample(ctx context.Context, a frontend.SessionAccess, id string, ...) (frontend.ReportOutcome, error)
- func (b *Broker) ResolveDetailSource(ctx context.Context, scope frontend.VersionScope, handle string) (frontend.DetailSourceTarget, error)
- func (b *Broker) ResolvePlexStream(ctx context.Context, access frontend.SessionAccess, wireID int64) (PlexStreamBinding, error)
- func (b *Broker) ServeMedia(w http.ResponseWriter, r *http.Request)
- func (b *Broker) ServeMediaAccess(w http.ResponseWriter, r *http.Request, a frontend.SessionAccess)
- func (b *Broker) ServeMediaFor(protocol frontend.Protocol, w http.ResponseWriter, r *http.Request)
- func (b *Broker) ServeSessionMedia(w http.ResponseWriter, r *http.Request, a frontend.SessionAccess, ...)
- func (b *Broker) Sessions(ctx context.Context, a frontend.SessionAccess) ([]frontend.Session, error)
- func (b *Broker) StartStream(ctx context.Context, a frontend.SessionAccess, id string, ...) (string, error)
- func (b *Broker) Stop(ctx context.Context, a frontend.SessionAccess, id string) error
- func (b *Broker) StopPlayback(ctx context.Context, playID string) bool
- func (b *Broker) StopProtocol(ctx context.Context, protocol frontend.Protocol) error
- func (b *Broker) SubtitleURL(ctx context.Context, a frontend.SessionAccess, id string, index int, ...) (string, error)
- func (b *Broker) TranscodeFor(_ context.Context, id string) (core.HLSSession, bool)
- func (b *Broker) TrickplayOffer(ctx context.Context, a frontend.SessionAccess, item core.RatingKey) (frontend.TrickplayOffer, bool)
- func (b *Broker) TrickplaySheet(ctx context.Context, a frontend.SessionAccess, item core.RatingKey, index int) ([]byte, error)
- func (b *Broker) UpdateCapabilities(ctx context.Context, a frontend.SessionAccess, c frontend.SessionCapabilities) error
- func (b *Broker) UpsertPlexActivity(id string, fn func(*PlexActivity)) PlexActivity
- type BrokerDeps
- type Coordination
- type DecisionRequest
- type Estimator
- type EventBus
- type LazyGrants
- type Lifecycle
- type LiveBackend
- type LiveMediaBackend
- type PlaybackOwners
- type PlexActivity
- type PlexAdmission
- type PlexStreamAPI
- type PlexStreamBinding
- type PlexStreamTable
- type ProfileDiagnostic
- type ProgressWriter
- type Selections
- type SourceHistoryWriter
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func BindEvents ¶
func BindEvents(events frontend.Subscriber, protocol frontend.Protocol) frontend.Subscriber
BindEvents applies the originating surface filter to user-data events.
func BindSurface ¶
BindSurface prevents an adapter from submitting another surface's identity.
func Decide ¶
func Decide(playback core.Playback, transcoder core.Transcoder, r DecisionRequest) (core.Decision, error)
Decide preserves the playback remux override for on-demand sources and stops the source when a required converter is unavailable.
func Estimate ¶
func Estimate(ctx context.Context, playback Estimator, viewer *core.Viewer, clientID string, title *core.Title, caps func() core.ClientCaps) (core.MediaInfo, *core.PlaySession)
Estimate returns an existing source's media information or a virtual estimate. It never prepares or resolves a release.
func HLSDecision ¶
func HLSDecision(dec core.Decision, allowDirect bool, reconsider func() core.Decision, forcedStream func(core.Decision) core.Decision) core.Decision
HLSDecision applies the v39 start-time decision rules. A client may reject direct play after its initial decision; in that case reconsider is called before selecting the segmented output. forcedStream, when supplied, applies adapter output constraints only when a still-direct decision is forced to HLS.
func NewLANLazyStreams ¶
func NewLANLazyStreams(db *sql.DB, broker *Broker, clientIP func(*http.Request) (netip.Addr, bool), viewer func(context.Context, *http.Request) (*core.Viewer, error), ttl time.Duration) (frontend.LANLazyStreams, error)
NewLANLazyStreams derives authority from host-owned peer and viewer checks. Capabilities are bound to that viewer, canonical peer device and item.
func NewLazyStreams ¶
func NewLazyStreams(db *sql.DB, b *Broker, protocol frontend.Protocol, grants LazyGrants, ttl time.Duration, remote func(*http.Request) bool) (frontend.LazyStreams, error)
NewLazyStreams creates a surface-bound durable, reusable capability issuer. Capabilities expire after at most one hour of inactivity and are revalidated on every request.
func NewSourceOffers ¶
func NewVersionHandles ¶
func NewVersionHandles(db *sql.DB, b *Broker, protocol frontend.Protocol) (frontend.VersionHandles, error)
NewVersionHandles creates a surface-bound, durable version identifier map. Handles are not credentials and all lookups recheck viewer and title policy.
func NotifyTranscodeActivity ¶
func NotifyTranscodeActivity(transcoder core.Transcoder, id, state string)
NotifyTranscodeActivity forwards timeline state to an active output. It is deliberately a no-op for transcoders and outputs without this capability.
func PlexStreamSlot ¶
func PlexStreamSlot(index int, info core.StreamInfo) string
PlexStreamSlot is the stable identity of a stream within a title. A subtitle's id is its language, codec, and source (the sidecar URL, or embedded), not its position in a variant's stream list. Play Version reorders those lists as candidates warm, and the same part id can name a different release; the viewer's choice has to keep naming the same track.
func PlexStreamsMatch ¶
func PlexStreamsMatch(a, b core.StreamInfo) bool
PlexStreamsMatch reports whether two renders are the same visible stream.
func PlexWireID ¶
PlexWireID is the positive int32-range id Plex clients already parse. Offer rows use it directly and are not stream bindings.
func RecordProgress ¶
func RecordProgress(ctx context.Context, writer ProgressWriter, viewer int64, key core.RatingKey, position, duration time.Duration, state string) error
RecordProgress preserves the existing treatment of extras, which do not enter the viewer's library watch history.
func Recover ¶
func Recover[R any](ctx context.Context, table *BindingTable[R], playback any, id, inputURL string, at time.Duration) error
Recover maps an encoder identifier to the source that owns it. Playback verifies the input generation before it attempts failover.
func TranscodeFor ¶
func TranscodeFor[R any](table *BindingTable[R], transcoder core.Transcoder, playID string) (core.HLSSession, bool)
TranscodeFor finds the running encoder fed by a playback source.
func WithPlexAdmission ¶
func WithPlexAdmission(ctx context.Context, admit func(context.Context) (PlexAdmission, error)) context.Context
WithPlexAdmission attaches the prepared source for one Plex Plan call.
Types ¶
type Binding ¶
type Binding[R any] struct { ID string // client "session" param StreamToken string // independent random capability; never a client-chosen ID PlayID string // core.PlaySession.ID PlaybackID string // explicit X-Plex-Session-IDentifier owning this encoder UserID int64 ClientID string Key core.RatingKey Requested R // original Decision/start inputs, before policy refinement Decision core.Decision Info core.MediaInfo Subtitle int // selected Subtitle's position in Info, -1 = none Caps core.ClientCaps Opts core.DecideOptions Offset time.Duration Started bool // StartHLS ran UpdatedAt time.Time // A failed Decision for this binding (FailKey, FailErr at FailedAt): // the start request that follows it answers with the same error at // once instead of resolving again. One-shot and short-lived. FailKey core.RatingKey FailErr error FailedAt time.Time }
type BindingTable ¶
type BindingTable[R any] struct { // contains filtered or unexported fields }
func NewBindingTable ¶
func NewBindingTable[R any]() *BindingTable[R]
func (*BindingTable[R]) ByPlayID ¶
func (t *BindingTable[R]) ByPlayID(PlayID string) []string
ByPlayID returns the transcode session ids fed by a playback session.
func (*BindingTable[R]) Claim ¶
Claim reserves a client-chosen ID before any playback/transcoder work. A different viewer or device cannot replace, reuse, stop, or probe that binding.
func (*BindingTable[R]) Fail ¶
func (t *BindingTable[R]) Fail(ID string, UserID int64, ClientID string, Key core.RatingKey, err error, now time.Time)
Fail records a failed Decision on the binding the Decision claimed. A binding owned by another viewer or device is left alone.
func (*BindingTable[R]) IDs ¶
func (t *BindingTable[R]) IDs() []string
IDs lists every binding this table still holds.
func (*BindingTable[R]) Put ¶
func (t *BindingTable[R]) Put(e *Binding[R])
func (*BindingTable[R]) Remove ¶
func (t *BindingTable[R]) Remove(ID string)
type Broker ¶
type Broker struct {
// contains filtered or unexported fields
}
Broker coordinates playback admission for every protocol, including Plex.
func NewBroker ¶
func NewBroker(d BrokerDeps) (*Broker, error)
func UnderlyingBroker ¶
UnderlyingBroker unwraps a surface binding to the broker that stores Plex activities. A non-broker Sessions value has none.
func (*Broker) BindPlexStream ¶
func (b *Broker) BindPlexStream(_ context.Context, access frontend.SessionAccess, binding PlexStreamBinding) (int64, error)
BindPlexStream assigns the visible id. WireID on the binding must be zero. Library metadata calls this before a viewer is known, so it does not authorize. Resolve and Open do.
func (*Broker) Capabilities ¶
func (b *Broker) Capabilities(ctx context.Context, a frontend.SessionAccess) (frontend.SessionCapabilities, error)
func (*Broker) Command ¶
func (b *Broker) Command(ctx context.Context, actor *core.Viewer, id string, cmd frontend.Command) error
Command targets one authenticated viewer's session. An active, non-delegated owner may target any viewer's session.
func (*Broker) ConfirmPlexAdmission ¶
func (b *Broker) ConfirmPlexAdmission(ctx context.Context, v *core.Viewer, remote bool) (*core.Viewer, error)
ConfirmPlexAdmission is the fenced policy check a Plex plan uses. planPlexAdmission already calls confirm with the request caps. This is the same check when the caller has only the remote bit.
func (*Broker) DetailPlan ¶
func (b *Broker) DetailPlan(ctx context.Context, req frontend.PlanRequest) (frontend.PlayPlan, error)
DetailPlan is for a single explicitly requested playable item, never a listing. The flight is scoped to the authenticated request and bounded. An informational result cannot be opened as a session by the caller.
func (*Broker) EnsurePlexActivity ¶
func (*Broker) ExpirePlexActivities ¶
func (*Broker) HasBinding ¶
HasBinding reports whether this broker owns an encoder ID.
func (*Broker) HasPlexActivity ¶
func (*Broker) ListPlexActivities ¶
func (b *Broker) ListPlexActivities() []PlexActivity
func (*Broker) Markers ¶
func (b *Broker) Markers(ctx context.Context, access frontend.SessionAccess, id string) (frontend.SessionMarkers, error)
Markers never borrows title-only or duration-only marker caches. It requires a complete provider result for the session's exact current source revision.
func (*Broker) MatchDetailSession ¶
func (b *Broker) MatchDetailSession(ctx context.Context, scope frontend.VersionScope, handle, sessionID string) error
MatchDetailSession authorizes an existing session only when it is pinned to the offered source and the authenticated viewer/device/surface still match.
func (*Broker) NotePlexEncoder ¶
func (b *Broker) NotePlexEncoder(id string, format frontend.StreamFormat, decision core.Decision, offset time.Duration)
NotePlexEncoder records that the Plex adapter started ffmpeg under the client transcode id, which is also the broker session id.
func (*Broker) OpenPlexSidecar ¶
func (b *Broker) OpenPlexSidecar(ctx context.Context, access frontend.SessionAccess, receipt auth.Acceptance, wireID int64) (io.ReadCloser, core.StreamInfo, error)
OpenPlexSidecar returns an external sidecar only after the acceptance, fenced policy, stream binding, and session agree. Failure returns no reader.
func (*Broker) PlexSessionForPlayback ¶
func (b *Broker) PlexSessionForPlayback(ctx context.Context, a frontend.SessionAccess, item frontend.RatingKey, playbackID, transcodeID string) (string, error)
PlexSessionForPlayback resolves the broker session for a Plex timeline. A client transcode id wins. Otherwise the playback header selects the newest match. An empty header matches only when exactly one session exists.
func (*Broker) PlexSessionForSource ¶
func (b *Broker) PlexSessionForSource(ctx context.Context, a frontend.SessionAccess, item frontend.RatingKey, playID string) (string, error)
PlexSessionForSource is the broker session that owns a prepared source for this viewer and item. The newest match wins when more than one remains.
func (*Broker) PlexSessionSource ¶
PlexSessionSource is the playback source owned by a published Plex session.
func (*Broker) RemovePlexActivity ¶
func (b *Broker) RemovePlexActivity(id string) (PlexActivity, bool)
func (*Broker) ReportItemProgress ¶
func (b *Broker) ReportItemProgress(ctx context.Context, a frontend.SessionAccess, item core.RatingKey, t frontend.Timeline) error
ReportItemProgress records a Jellyfin or Emby timeline that names an item instead of a broker session.
func (*Broker) ReportProgress ¶
func (b *Broker) ReportProgress(ctx context.Context, a frontend.SessionAccess, item core.RatingKey, t frontend.Timeline) error
ReportProgress records a Plex timeline that has no playback source. It does not prepare or stop one.
func (*Broker) ReportSample ¶
func (b *Broker) ReportSample(ctx context.Context, a frontend.SessionAccess, id string, sample frontend.ProgressSample) (frontend.ReportOutcome, error)
ReportSample uses the same policy and ownership gate as ordinary reporting, but requires a synchronous receipt writer instead of the availability outbox.
func (*Broker) ResolveDetailSource ¶
func (b *Broker) ResolveDetailSource(ctx context.Context, scope frontend.VersionScope, handle string) (frontend.DetailSourceTarget, error)
func (*Broker) ResolvePlexStream ¶
func (b *Broker) ResolvePlexStream(ctx context.Context, access frontend.SessionAccess, wireID int64) (PlexStreamBinding, error)
ResolvePlexStream returns a bound stream. An unknown id is ErrNotFound. A viewer who may not play is ErrUnauthorized, not a miss.
func (*Broker) ServeMedia ¶
func (b *Broker) ServeMedia(w http.ResponseWriter, r *http.Request)
ServeMedia validates a session-scoped capability on every request.
func (*Broker) ServeMediaAccess ¶
func (b *Broker) ServeMediaAccess(w http.ResponseWriter, r *http.Request, a frontend.SessionAccess)
ServeMediaAccess additionally binds the grant to the authenticated device.
func (*Broker) ServeMediaFor ¶
ServeMediaFor binds a mounted handler to its protocol surface.
func (*Broker) ServeSessionMedia ¶
func (b *Broker) ServeSessionMedia(w http.ResponseWriter, r *http.Request, a frontend.SessionAccess, sessionID, resource string)
ServeSessionMedia serves one session resource for a device that already proved it owns the session. The grant stays on the internal path; callers must not copy it into a client URL.
func (*Broker) StartStream ¶
func (b *Broker) StartStream(ctx context.Context, a frontend.SessionAccess, id string, req frontend.StreamRequest) (string, error)
func (*Broker) StopPlayback ¶
StopPlayback stops every local broker session fed by a source ID.
func (*Broker) StopProtocol ¶
StopProtocol releases every local session for one mounted surface.
func (*Broker) SubtitleURL ¶
func (b *Broker) SubtitleURL(ctx context.Context, a frontend.SessionAccess, id string, index int, format string) (string, error)
SubtitleURL authorizes a subtitle by the session's probed stream index. The returned URL contains only the scoped stream capability.
func (*Broker) TranscodeFor ¶
func (*Broker) TrickplayOffer ¶
func (b *Broker) TrickplayOffer(ctx context.Context, a frontend.SessionAccess, item core.RatingKey) (frontend.TrickplayOffer, bool)
TrickplayOffer revalidates the viewer, item, version, and source generation before advertising tiles. A false offer leaves the Jellyfin map empty.
func (*Broker) TrickplaySheet ¶
func (b *Broker) TrickplaySheet(ctx context.Context, a frontend.SessionAccess, item core.RatingKey, index int) ([]byte, error)
TrickplaySheet composes one JPEG grid from the borrowed provider's frames.
func (*Broker) UpdateCapabilities ¶
func (b *Broker) UpdateCapabilities(ctx context.Context, a frontend.SessionAccess, c frontend.SessionCapabilities) error
UpdateCapabilities stores declarations for the authenticated device only. URL metadata is never dereferenced by the broker.
func (*Broker) UpsertPlexActivity ¶
func (b *Broker) UpsertPlexActivity(id string, fn func(*PlexActivity)) PlexActivity
type BrokerDeps ¶
type BrokerDeps struct {
Coordination *Coordination
// MaxPendingStarts bounds active or waiting neutral stream starts.
// Zero selects the default; the broker rejects values above 4096.
MaxPendingStarts int
DB *sql.DB
Cluster clusterbus.Node
Live LiveBackend
Variants func(context.Context, *core.Viewer, *core.Title, core.ClientCaps) ([]core.ReleaseVariant, error)
SelectTracks func(context.Context, *core.Viewer, *core.Title, core.MediaInfo, core.DecideOptions, bool, bool) (core.DecideOptions, error)
// SelectScopedTracks receives the authenticated device as well. If present,
// it replaces SelectTracks and must preserve the unscoped behavior.
SelectScopedTracks func(context.Context, *core.Viewer, core.Device, *core.Title, core.MediaInfo, core.DecideOptions, bool, bool) (core.DecideOptions, error)
Lookup func(context.Context, *core.Viewer, core.Device, core.RatingKey) (*core.Title, error)
// MediaLookup checks current title policy using local facts only; it must
// never resolve a release or fetch remote metadata on a segment request.
// If nil, Lookup must satisfy the same requirement.
MediaLookup func(context.Context, *core.Viewer, core.Device, core.RatingKey) (*core.Title, error)
Playback core.Playback
Transcoder core.Transcoder
Progress ProgressWriter
SourceHistory SourceHistoryWriter
ActiveViewer func(context.Context, int64) (*core.Viewer, error)
CanPlay func(*core.Viewer, bool, time.Time) bool
// FreshPlay re-reads fenced membership and safety policy. A returned viewer
// replaces the cached one for the rest of the call. ErrPolicyUnconfirmed
// keeps the cached CanPlay decision for an unrestricted viewer.
FreshPlay func(context.Context, *core.Viewer, bool, time.Time) (*core.Viewer, error)
// ReceiptCurrent rechecks the acceptance Plex stored for this request.
ReceiptCurrent func(context.Context, auth.Acceptance) error
BitrateLimit func(*core.Viewer) int
RemoteBitrateLimit func() int
OnTimeline func(*core.Viewer, core.RatingKey, time.Duration, time.Duration, string)
Events *EventBus
OnEventError func(error)
// OnProfileDiagnostic is an optional fixture hook. Values are closed enums
// only; the callback receives no media, identity or client-supplied data.
OnProfileDiagnostic func(ProfileDiagnostic)
// SourceMarkers returns a complete marker set for the exact source revision.
SourceMarkers func(context.Context, *core.Viewer, core.RatingKey, string, core.MediaInfo) ([]frontend.Marker, bool, error)
OpenSubtitle func(string, string) (io.ReadCloser, string, error)
OpenSubtitleFrom func(string, string, string) (io.ReadCloser, string, error)
ExtractSubtitle func(context.Context, string, int, string, io.Writer) error
// Trickplay is borrowed from the runtime owner (internal/app/trickplay_owner.go).
// It is the same provider Plex uses. The broker releases its own leases;
// only the runtime owner may Close the provider.
Trickplay core.TrickplayProvider
Now func() time.Time
}
BrokerDeps are the explicit dependencies shared by all protocol surfaces.
type Coordination ¶
type Coordination struct {
Owners *PlaybackOwners
Gates *Lifecycle
}
Coordination holds the v39 playback owner history and lifecycle gates shared by every protocol adapter in one Ether process.
func NewCoordination ¶
func NewCoordination() *Coordination
type DecisionRequest ¶
type DecisionRequest struct {
Session *core.PlaySession
Caps core.ClientCaps
Options core.DecideOptions
PreferRemux bool
Protocol string
RemoteMaxBitrateKbps int
// PreserveSourceOnFailure lets a broker avoid stopping a reused source
// when an attempted decision cannot be served without a transcoder.
PreserveSourceOnFailure bool
}
DecisionRequest contains the source and client inputs for a playback decision. PreferRemux is the adapter's signal that source changes need refreshed container headers; the source and requested direct-stream mode still determine whether the override applies.
type Estimator ¶
type Estimator interface {
Estimate(context.Context, *core.Title, core.ClientCaps) core.MediaInfo
SessionFor(int64, string, core.RatingKey) (*core.PlaySession, bool)
}
Estimator is the non-resolving playback surface for detail pages.
type EventBus ¶
type EventBus struct {
// contains filtered or unexported fields
}
EventBus distributes viewer-scoped events locally and across cluster nodes. ActiveViewer must return the current active viewer, not a cached credential.
func NewEventBus ¶
func NewEventBus(bus clusterbus.Bus, activeViewer func(context.Context, int64) (*core.Viewer, error)) *EventBus
NewEventBus subscribes to cluster events when bus is non-nil. Call Close when the application shuts down.
type LazyGrants ¶
type LazyGrants interface {
GrantReference(context.Context, string, string) (string, *core.Viewer, error)
ValidateGrantReference(context.Context, string, string, int64) error
}
LazyGrants authenticates an issuing surface credential and rechecks the non-secret grant reference without extending its lifetime.
type Lifecycle ¶
type Lifecycle = playbackLifecycle
Lifecycle owns the v39 owner and encoder gates.
func NewLifecycle ¶
func NewLifecycle() *Lifecycle
type LiveBackend ¶
type LiveBackend interface {
Allowed(context.Context, *core.Viewer, string) error
Tune(context.Context, *core.Viewer, string, core.ClientCaps, string) (string, error)
Serve(http.ResponseWriter, *http.Request, *core.Viewer, string, string, string)
Stop(context.Context, *core.Viewer, string) error
}
LiveBackend adapts the existing channel playout service. Serve receives a grant-validated request and a path relative to the scoped live stream.
type LiveMediaBackend ¶
type LiveMediaBackend interface {
LiveBackend
TuneMedia(context.Context, *core.Viewer, string, core.ClientCaps, string) (string, *core.MediaInfo, error)
}
LiveMediaBackend optionally returns the live session's probed or output MediaInfo.
type PlaybackOwners ¶
type PlaybackOwners = playbackOwners
PlaybackOwners retains the v39 playback handoff and supersession rules.
func NewPlaybackOwners ¶
func NewPlaybackOwners() *PlaybackOwners
type PlexActivity ¶
type PlexActivity struct {
ID string
SessionKey int
User core.User
ClientID, Product, Version, Platform, PlatformVersion string
Device, DeviceName, Model, Vendor, SessionID, RemoteIP string
Remote bool
Key core.RatingKey
State string
Offset, Duration time.Duration
PlayQueueItemID int64
TranscodeID string
StartedAt, UpdatedAt time.Time
}
PlexActivity is one Plex client's playback as the session list shows it. The broker is the only store. Cluster rows for these activities use protocol plex.
type PlexAdmission ¶
type PlexAdmission struct {
Source *core.PlaySession
Media core.MediaInfo
Caps core.ClientCaps
Options core.DecideOptions
PreferRemux bool
Protocol string
RemoteMaxBitrateKbps int
}
PlexAdmission is the source and the version and track selections for one Plex plan. Plan makes the direct, remux, or transcode decision from them. Open publishes that decision. The adapter renders it and does not decide again.
type PlexStreamAPI ¶
type PlexStreamAPI interface {
BindPlexStream(context.Context, frontend.SessionAccess, PlexStreamBinding) (int64, error)
ResolvePlexStream(context.Context, frontend.SessionAccess, int64) (PlexStreamBinding, error)
OpenPlexSidecar(context.Context, frontend.SessionAccess, auth.Acceptance, int64) (io.ReadCloser, core.StreamInfo, error)
}
PlexStreamAPI is the visible-id and sidecar surface Plex calls.
func BindPlexStreams ¶
func BindPlexStreams(b *Broker) PlexStreamAPI
BindPlexStreams is BindSurface for the Plex stream methods. The returned value rejects any access whose protocol is not plex.
type PlexStreamBinding ¶
type PlexStreamBinding struct {
WireID int64
SessionID string
Key core.RatingKey
Index int
Info core.StreamInfo
}
PlexStreamBinding is one Plex-visible stream id. WireID is zero on bind; BindPlexStream assigns it. SessionID is empty for library metadata and is the broker session id after Open.
type PlexStreamTable ¶
type PlexStreamTable struct {
// contains filtered or unexported fields
}
PlexStreamTable is the visible-id map. Plex offer ids are not stored here.
func NewPlexStreamTable ¶
func NewPlexStreamTable() *PlexStreamTable
NewPlexStreamTable is the visible-id map used by the broker and by Plex fixtures that have no broker mounted.
func (*PlexStreamTable) Bind ¶
func (t *PlexStreamTable) Bind(binding PlexStreamBinding) (int64, error)
Bind assigns or reuses the wire id for this slot. It does not authorize.
func (*PlexStreamTable) Lookup ¶
func (t *PlexStreamTable) Lookup(id int64) (PlexStreamBinding, bool)
Lookup reports the binding. False means the id was never bound.
type ProfileDiagnostic ¶
type ProfileDiagnostic string
ProfileDiagnostic is a redacted reason emitted only to an explicitly installed diagnostic hook. It never includes client profile values.
const ( ProfileRequiredConditionUnknown ProfileDiagnostic = "required_condition_unknown" ProfileDirectRejected ProfileDiagnostic = "direct_rejected" ProfileDeliveryRejected ProfileDiagnostic = "delivery_rejected" ProfileFallbackTranscode ProfileDiagnostic = "fallback_transcode" ProfileFallbackRemux ProfileDiagnostic = "fallback_remux" ProfileNoDelivery ProfileDiagnostic = "no_delivery" )
type ProgressWriter ¶
type ProgressWriter interface {
Progress(context.Context, int64, core.RatingKey, time.Duration, time.Duration, string) error
}
ProgressWriter persists the timeline after the caller has checked ownership.
type Selections ¶
type Selections[T any] struct { // contains filtered or unexported fields }
Selections stores per-viewer track choices. The adapter owns the value shape and translates wire stream identifiers before updating a choice.
func NewSelections ¶
func NewSelections[T any]() *Selections[T]
func (*Selections[T]) Get ¶
func (s *Selections[T]) Get(viewer, item int64) T
func (*Selections[T]) Update ¶
func (s *Selections[T]) Update(viewer, item int64, fn func(*T))
type SourceHistoryWriter ¶
type SourceHistoryWriter interface {
BeginSourceSession(context.Context) (int64, error)
RecordLastSource(context.Context, int64, core.RatingKey, int64, int64, core.PlaybackSourceObservation) error
}
SourceHistoryWriter stores facts from accepted samples, ordered first by session epoch and then by the sample number assigned before persistence. Implementations must honor cancellation, including during transaction commit. The production state writer uses context-aware SQLite/PostgreSQL operations. Go cannot forcibly stop an implementation or driver that ignores context.
Source Files
¶
- activity.go
- alternatives.go
- bindings.go
- broker.go
- capabilities.go
- capacity.go
- client_profiles.go
- cluster.go
- cluster_store.go
- command.go
- coordination.go
- decision.go
- delivery_authority.go
- detail_plan.go
- detail_source.go
- estimate.go
- events.go
- flight_transfer.go
- lazy.go
- lazy_bounds.go
- lazy_cleanup.go
- lazy_lan.go
- lazy_schema.go
- lifecycle.go
- live.go
- media.go
- ownership.go
- plan_leases.go
- plex_activity.go
- plex_admit.go
- plex_streams.go
- profile_decision.go
- progress.go
- recovery.go
- retirement_outcome.go
- revision.go
- sample_report.go
- sample_schema.go
- schema.go
- selection.go
- sequence.go
- session_events.go
- session_id.go
- session_markers.go
- source_history.go
- source_offer_schema.go
- source_offers.go
- source_tracks.go
- subtitles.go
- superseded.go
- surface.go
- trickplay.go
- version_handles.go
- viewer_lifecycle.go