Documentation
¶
Overview ¶
Package plex is Ether's Plex Media Server front end: the HTTP API that official Plex apps (Web, iOS, Apple TV, Android, TVs) talk to. Everything behind it is reached through internal/core interfaces.
Index ¶
- Constants
- func RouteInventory() conform.RouteInventory
- type AccessPolicy
- type CollectionArtworker
- type Deps
- type Directive
- type DiscoveryFeatures
- type ExtrasProvider
- type Frontend
- type FrontendArtwork
- func (a FrontendArtwork) ChannelImage(v *core.Viewer, c livetv.Channel) frontend.Image
- func (a FrontendArtwork) List(ctx context.Context, req frontend.ArtworkRequest) ([]frontend.Image, bool, error)
- func (a FrontendArtwork) Read(ctx context.Context, req frontend.ArtworkRequest, img frontend.Image, ...) ([]byte, string, error)
- func (a FrontendArtwork) Warm(t core.Title, d core.Device)
- type Hooks
- type Identity
- type MarkerProvider
- type Request
- type Section
- type Server
- func (s *Server) Close() error
- func (s *Server) Closed() bool
- func (s *Server) DownloadsAllowed(u *core.User) bool
- func (s *Server) LibrarySections() []Section
- func (s *Server) NoteOwnerStop(id, reason string)
- func (s *Server) NotifyLiveLineup()
- func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request)
- func (s *Server) UsePlaybackBroker(b frontend.Sessions)
- func (s *Server) UsePlexStreams(api sessions.PlexStreamAPI)
- func (s *Server) WatchStateChanged(userID int64, key core.RatingKey)
- type SessionToucher
- type SubtitleCatalog
- type SubtitleOffer
- type SubtitleSearch
- type SubtitleSource
- type SubtitleTimeline
- type SubtitleUpload
- type TrackPreferences
Constants ¶
const APIVersion = "1.2.3"
APIVersion is the PMS API version Ether implements (X-Plex-Pms-Api-Version).
const DefaultPMSVersion = "1.43.4.10903-e5521bd8c"
DefaultPMSVersion is reported when Identity.Version is empty. Clients gate features on the server version, so it must look like a current PMS build.
Variables ¶
This section is empty.
Functions ¶
func RouteInventory ¶ added in v0.3.0
func RouteInventory() conform.RouteInventory
RouteInventory enumerates the same registration tree used by the server, without starting background workers or needing runtime dependencies.
Types ¶
type AccessPolicy ¶
type AccessPolicy = experience.AccessPolicy
AccessPolicy adds owner-defined restrictions to the mandatory title guard.
type CollectionArtworker ¶
type CollectionArtworker interface {
CollectionArtwork(ctx context.Context, user *core.User, key core.RatingKey, element string, width int) (data []byte, contentType string, ok bool, err error)
}
CollectionArtworker is optionally implemented by Deps.Collections to serve generated collection posters (internal/collections renders them with internal/artwork). ok=false falls back to the TMDB artwork path.
type Deps ¶
type Deps struct {
ArtworkImages *artworkservice.RemoteCache
ArtworkPalettes *artworkservice.PaletteCache
SessionCoordination *sessions.Coordination
FavoriteShows func(context.Context, *core.User) (map[core.RatingKey]bool, error)
FilterAvailable func(context.Context, []core.Title) []core.Title
PrioritizeAvailable func(context.Context, []core.Title) []core.Title
EpisodeOrder *episodeorder.Service
PlexGUID *plexguid.Service
PlexMeta *plexmeta.Service
Discovery *DiscoveryFeatures
LiveTV *livetv.Service
AccessPolicy AccessPolicy
Catalog core.Catalog
Collections core.Collections
VibeSearch core.VibeSearcher
Recommender core.Recommender
State core.State
Playlists core.Playlists
Auth core.Auth
Playback core.Playback
Transcoder core.Transcoder
// Variants lists distinct release versions for "Play Version" detail
// pages (optional: without it, detail pages stay single-Media).
Variants core.VariantResolver
// DecisionTraces is the latest resolution for a title, copied into a
// support capture. Nil leaves playback unchanged.
DecisionTraces core.DecisionTraceSource
// Downloads remuxes resolved sources to temp MP4s for the Download
// Queue API; nil disables downloads (allowSync stays "0").
Downloads core.DownloadRemuxer
TrackPreferences TrackPreferences
Markers MarkerProvider
Subtitles SubtitleSource
Extras ExtrasProvider
Trickplay core.TrickplayProvider
// ApplyClientRules adjusts caps for the owner's quality rules. Nil leaves
// the request caps unchanged. The app wires resolver.ApplyClientRules so
// this package stays outside the resolver.
ApplyClientRules func(config.Quality, core.ClientCaps, *core.User) core.ClientCaps
// Config returns the current settings snapshot.
Config func() config.Config
// OwnerSubscription returns the current entitlement snapshot from plex.tv.
OwnerSubscription func() (active bool, features []string)
// ImageURL builds TMDB image URLs; defaults to image.tmdb.org.
ImageURL core.ImageURLFunc
Logger *slog.Logger
Identity Identity
Hooks Hooks
// Sections overrides the default Movies (1) and TV Shows (2) sections.
Sections []Section
// HTTPClient fetches artwork for the image proxy; defaults to a client
// with a 20 s timeout. The app wires the metadata route so this package
// does not import the egress policy.
HTTPClient *http.Client
// DirectHTTP proxies trailer bytes. Nil uses the default transport.
// The app wires the direct route so this package does not import egress.
DirectHTTP *http.Client
// ImageCacheBytes bounds the in-memory artwork cache (default 128 MiB).
ImageCacheBytes int64
// DB persists derived artwork data (UltraBlurColors) in plex_* tables.
// Optional: without it, colours are kept in memory only.
DB *sql.DB
// DisableEnrichment turns off the background title-detail and
// UltraBlurColors work (the spike test library has nothing to fetch).
DisableEnrichment bool
// Cluster, when set (clustered nodes only; requires DB), shares play
// sessions, play queues, terminations and notifications with the other
// nodes. Nil keeps everything in this process.
Cluster clusterbus.Node
// SessionHeartbeat is how often a clustered node refreshes its shared
// play sessions (default 10s).
SessionHeartbeat time.Duration
// Now is the clock (tests).
Now func() time.Time
// Dashboard is this node's in-memory Plex Web Dashboard store. Nil is
// replaced with a process-local store at NewServer. Statistics are not
// clustered; a client reads the node it connected to.
Dashboard *stats.Dashboard
// Resources is this node's host sample ring for /statistics/resources.
Resources *hoststat.Resources
// Support records neutral request and playback facts. Nil leaves playback unchanged.
Support *diagnostics.Recorder
// TracePlayback logs HLS/transcode requests when ETHER_TRACE_PLAYBACK=1.
// It does not change responses.
TracePlayback bool
}
Deps are the server's dependencies. Catalog, State, Auth and Playback are required; the rest degrade gracefully when nil.
type Directive ¶
Directive is one parsed X-Plex-Client-Profile-Extra directive, e.g. add-limitation(scope=videoCodec&scopeName=h264&...).
func ParseProfileExtra ¶
ParseProfileExtra splits a profile-extra string into directives. The value may arrive URL-encoded; directives are separated by "+".
type DiscoveryFeatures ¶
DiscoveryFeatures is the shared discovery service adapted by Plex.
type ExtrasProvider ¶
type ExtrasProvider interface {
Enabled() bool
List(ctx context.Context, parent *core.Title, lang string) ([]extras.Extra, error)
Lookup(key core.RatingKey) (extras.Extra, bool)
Resolve(ctx context.Context, e extras.Extra) (extras.Resolved, error)
PrewarmBytes() int64
}
ExtrasProvider is the extras service surface the front end needs (*extras.Service satisfies it).
type Frontend ¶ added in v0.3.0
type Frontend struct {
NewServer func() (*Server, error)
Server *Server
WatchState *state.State
// ExplicitWatchOnly preserves spike mode: only cross-surface scrobbles refresh.
ExplicitWatchOnly bool
StatusFunc func(context.Context) frontend.Status
ListenersFunc func() []frontend.ListenerSpec
}
Frontend adapts the existing PMS handler to the frontend registry. Unmount stops this mount's broker sessions, encoders, trickplay, and downloads, and drops its watch subscription. The process-owned server stays up so an in-flight request can finish.
func (Frontend) Describe ¶ added in v0.3.0
func (f Frontend) Describe() frontend.Descriptor
type FrontendArtwork ¶ added in v0.3.0
type FrontendArtwork struct {
Server *Server
Variants func(*core.Title, string) (*tmdb.Images, bool)
Metadata func(context.Context, frontend.ArtworkRequest, frontend.Image) frontend.Image
VirtualSeason func(context.Context, *core.User, core.RatingKey) (*core.Title, error)
URLImages interface {
GetUntrustedURL(context.Context, string) ([]byte, string, error)
}
Raster *artwork.SVGRasterizer
}
FrontendArtwork is a compatibility adapter for callers already holding a Plex server. Shared runtime constructs artworkservice.Source directly.
func (FrontendArtwork) ChannelImage ¶ added in v0.3.0
func (FrontendArtwork) List ¶ added in v0.3.0
func (a FrontendArtwork) List(ctx context.Context, req frontend.ArtworkRequest) ([]frontend.Image, bool, error)
func (FrontendArtwork) Read ¶ added in v0.3.0
func (a FrontendArtwork) Read(ctx context.Context, req frontend.ArtworkRequest, img frontend.Image, tr frontend.ArtworkTransform) ([]byte, string, error)
type Hooks ¶
type Hooks struct {
// OnClientSeen receives the client identifier after authentication.
OnClientSeen func(clientID string)
// OnTimeline is called for every timeline update (prefetch uses it).
OnTimeline func(user *core.User, key core.RatingKey, offset, duration time.Duration, state string)
// OnScrobble is called when a user marks an item watched.
OnScrobble func(user *core.User, key core.RatingKey)
}
Hooks are optional callbacks into other components. They run on their own goroutine and must be safe for concurrent use.
type Identity ¶
type Identity struct {
MachineIdentifier string
FriendlyName string
Version string // PMS-style version string
Platform string // "MacOSX", "Windows", "Linux"
PlatformVersion string
// MyPlexSubscription reports whether the owner has Plex Pass; Ether
// reports this honestly from plex.tv.
MyPlexSubscription bool
OwnerFeatures []string
}
Identity is how the server presents itself. Empty fields fall back to the config snapshot (friendly name, machine identifier) or sensible defaults.
type MarkerProvider ¶
type Request ¶
type Request struct {
Token string
ClientID string // X-Plex-Client-Identifier
Product string // X-Plex-Product
Version string // X-Plex-Version
Platform string // X-Plex-Platform
PlatformVersion string // X-Plex-Platform-Version
Device string // X-Plex-Device
DeviceName string // X-Plex-Device-Name
Model string // X-Plex-Model
Vendor string // X-Plex-Device-Vendor
Language string // X-Plex-Language
Marketplace string // X-Plex-Marketplace
Provides string // X-Plex-Provides
Features string // X-Plex-Features
ProfileExtra string // X-Plex-Client-Profile-Extra
ProfileName string // X-Plex-Client-Profile-Name
ClientCapabilities string // X-Plex-Client-Capabilities (legacy)
SessionID string // X-Plex-Session-Identifier
PMSAPIVersion string // X-Plex-Pms-Api-Version
// Paging (X-Plex-Container-Start/Size); HasPage is false when the client
// did not ask for a window.
Start int
Size int
HasPage bool
Format model.Format
RemoteIP netip.Addr
Remote bool // not on a private/loopback network
User *core.User
// Capability is set when authentication used a stream grant or other
// session-scoped credential, not a user token. Only transcode
// session/segment handlers may serve a capability-scoped request.
Capability bool
}
Request is the parsed Plex request context: every X-Plex-* header (or its query-string equivalent), paging, the output format and the remote address.
func FromContext ¶
FromContext returns the request context attached by the middleware.
func ParseRequest ¶
ParseRequest builds the request context from an HTTP request. Forwarded addresses are considered only for a loopback peer (a local reverse proxy).
func (*Request) ClientCaps ¶
func (pr *Request) ClientCaps(remoteMaxKbps int) core.ClientCaps
ClientCaps derives core.ClientCaps for the request. remoteMaxKbps caps the bitrate of remote clients (0 = unlimited).
func (*Request) ClientCapsWith ¶ added in v0.3.0
func (pr *Request) ClientCapsWith(remoteMaxKbps int, overrides []core.ClientCapabilityOverride) core.ClientCaps
ClientCapsWith is ClientCaps with owner registry overrides applied before the request's own profile and capability headers.
type Section ¶
type Section struct {
ID int
Type core.MediaType // movie or show
Title string
UUID string // stable; derived from the machine identifier when empty
Language string
}
Section is a library section exposed to clients.
type Server ¶
type Server struct {
// contains filtered or unexported fields
}
Server is the PMS API handler. It is an http.Handler; call Close on shutdown to stop background work and notification streams.
func (*Server) DownloadsAllowed ¶ added in v0.3.0
DownloadsAllowed exposes the same admission decision for informational frontend capability reporting; the download handler still enforces it.
func (*Server) LibrarySections ¶ added in v0.2.14
LibrarySections returns the canonical section identities for account registration. Titles follow the live config so renames publish to plex.tv. The copy prevents publishers from changing local libraries.
func (*Server) NoteOwnerStop ¶ added in v0.3.0
NoteOwnerStop tells the Plex client why a stream is ending. The shared broker stops the source.
func (*Server) NotifyLiveLineup ¶ added in v0.3.0
func (s *Server) NotifyLiveLineup()
NotifyLiveLineup tells connected Plex clients to reload the DVR lineup and guide. Channel create and delete call it through LiveTV.SetOnChange.
func (*Server) ServeHTTP ¶
func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request)
ServeHTTP implements http.Handler.
func (*Server) UsePlaybackBroker ¶ added in v0.3.0
UsePlaybackBroker attaches the shared session broker. Mounted Plex playback publishes through it. Timeline progress and stops are recorded only there.
func (*Server) UsePlexStreams ¶ added in v0.3.0
func (s *Server) UsePlexStreams(api sessions.PlexStreamAPI)
UsePlexStreams binds visible stream ids and sidecar reads to the broker. Pass sessions.BindPlexStreams(broker).
func (*Server) WatchStateChanged ¶ added in v0.2.11
WatchStateChanged invalidates client library metadata after a committed watch update. A playing notification only updates session status; clients can keep their cached Continue Watching shelf until a library timeline event arrives.
type SessionToucher ¶
type SessionToucher interface {
Touch(sessionID string)
}
SessionToucher is optionally implemented by core.Playback to keep a play session alive on timeline updates.
type SubtitleCatalog ¶ added in v0.2.21
type SubtitleCatalog interface {
CachedSidecars(ctx context.Context, t *core.Title, u *core.User, embedded []core.StreamInfo) []core.StreamInfo
}
SubtitleCatalog is optionally implemented by Deps.Subtitles: the sidecars already cached for a title and viewer, without network access, skipping streams embedded already lists (by ExternalURL) or covers (by language).
type SubtitleOffer ¶ added in v0.2.21
type SubtitleOffer struct {
ID int64 // provider file id, passed back to DownloadSubtitle
Language string // ISO 639-1
Title string // release or file name
Provider string // "OpenSubtitles"
Score int
HearingImpaired bool
Forced bool
PerfectMatch bool // matched the playing file's hash or release
}
SubtitleOffer is one subtitle search result.
type SubtitleSearch ¶ added in v0.2.21
type SubtitleSearch interface {
SearchSubtitles(ctx context.Context, t *core.Title, u *core.User, lang, release string) ([]SubtitleOffer, error)
// DownloadSubtitle fetches an offer returned by SearchSubtitles for t
// and returns its sidecar stream; core.ErrNotFound for unknown offers.
DownloadSubtitle(ctx context.Context, t *core.Title, u *core.User, id int64) (core.StreamInfo, error)
}
SubtitleSearch is optionally implemented by Deps.Subtitles: Plex's on-demand subtitle search and pick.
type SubtitleSource ¶
SubtitleSource resolves cached OpenSubtitles and synchronized sidecars.
type SubtitleTimeline ¶ added in v0.2.21
type SubtitleTimeline interface {
OpenFormatAt(id, format string, offset time.Duration) (io.ReadCloser, string, error)
}
SubtitleTimeline is optionally implemented by Deps.Subtitles: a sidecar with its cues moved back by offset, for a transcode that starts there.
type SubtitleUpload ¶ added in v0.3.0
type SubtitleUpload interface {
UploadSubtitle(ctx context.Context, t *core.Title, u *core.User, filename, format, language string, body []byte) (core.StreamInfo, error)
}
SubtitleUpload is optionally implemented by Deps.Subtitles: Plex Web's "Upload Subtitles" (POST /library/metadata/{key}/subtitles).
type TrackPreferences ¶
type TrackPreferences interface {
Select(context.Context, int64, core.RatingKey, core.MediaInfo, string) (trackprefs.Selection, error)
Remember(context.Context, int64, core.RatingKey, string, *core.StreamInfo) error
GetRules(context.Context, int64) (trackprefs.Rules, error)
}
TrackPreferences is optional. Selections are stream slice positions; saved show choices match language/flags so they survive changes in release order.
Source Files
¶
- artwork_policy.go
- background.go
- broker_publish.go
- broker_streams.go
- caps.go
- cluster.go
- collection_artwork.go
- continue_next.go
- convert.go
- discovery_features.go
- enrich.go
- frontend.go
- frontend_artwork.go
- handlers_dash.go
- handlers_downloads.go
- handlers_extras.go
- handlers_http.go
- handlers_hubs.go
- handlers_indexes.go
- handlers_library.go
- handlers_metadata.go
- handlers_playlists.go
- handlers_server.go
- handlers_state.go
- handlers_statistics.go
- home_layout.go
- images.go
- library_guid.go
- livetv_api.go
- livetv_native.go
- livetv_queue.go
- metadata_features.go
- middleware.go
- notify.go
- personal_hooks.go
- playback.go
- playback_lifecycle.go
- playqueue.go
- plexmeta.go
- recommendation_filter.go
- request.go
- route_inventory.go
- routes.go
- safety.go
- scheduled.go
- server.go
- slug.go
- stop.go
- stores.go
- stream_auth.go
- stream_read.go
- streams_features.go
- subtitles.go
- support_observe.go
- ultrablur.go
- variants.go
- watch_refresh.go
Directories
¶
| Path | Synopsis |
|---|---|
|
Package model holds the Plex Media Server response models and the encoder that renders one model as either PMS-style XML or PMS-style JSON.
|
Package model holds the Plex Media Server response models and the encoder that renders one model as either PMS-style XML or PMS-style JSON. |