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

service

package
v0.3.2 Latest Latest
Warning

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

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

Documentation

Overview

Package service owns shared artwork authorization, selection and rendering.

Index

Constants

View Source
const (
	MaxImageBytes = 15 << 20
)

Variables

View Source
var ErrRemoteImageNotFound = errors.New("image not found")

Functions

func RenderUltraBlur

func RenderUltraBlur(colors Palette, transform frontend.ArtworkTransform) ([]byte, string, error)

renderUltraBlur paints the same four colours Plex provides to its clients. Palette selection itself stays in the shared UltraBlur cache and pipeline.

func TMDBSize

func TMDBSize(w int) string

TMDBSize picks the smallest variant at least w wide, or "original".

func Transform

func Transform(data []byte, contentType string, transform frontend.ArtworkTransform) ([]byte, string, error)

Types

type CollectionArt

type CollectionArt interface {
	CollectionArtwork(context.Context, *core.User, core.RatingKey, string, int) ([]byte, string, bool, error)
}

CollectionArt is generated collection artwork. Smart-collection UltraBlur colours come from that image when it exists.

type LibraryCollageCache

type LibraryCollageCache struct {
	Dir string
	// contains filtered or unexported fields
}

LibraryCollageCache stores generated library-view JPEGs. The file name is the identity of the view and the child posters, so a content change stops serving the previous image.

type MetadataQueue

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

MetadataQueue joins stored width, height, and hash rows on the request. Missing descriptors are hashed by the background worker. A caller with a deadline may wait for a hash already in flight, and never longer than artworkInflightWait.

func (*MetadataQueue) Get

func (*MetadataQueue) Wait

func (q *MetadataQueue) Wait()

Wait joins workers after the owning context is cancelled.

func (*MetadataQueue) WaitIdle

func (q *MetadataQueue) WaitIdle(ctx context.Context) error

WaitIdle blocks until queued hashes have been stored or ctx ends.

type Palette

type Palette struct{ TopLeft, TopRight, BottomLeft, BottomRight string }

Palette holds neutral image corner colours, without protocol serialization flags.

func ComputeItemPalette

func ComputeItemPalette(ctx context.Context, cache *RemoteCache, imageURL core.ImageURLFunc, key core.RatingKey, path string, now time.Time, art CollectionArt) (Palette, error)

ComputeItemPalette derives UltraBlur colours for one catalogue item. A smart collection uses its generated art (custom collection art) when the lookup returns bytes; every other item uses the backdrop path.

func ComputePalette

func ComputePalette(ctx context.Context, cache *RemoteCache, imageURL core.ImageURLFunc, path string, now time.Time) (Palette, error)

ComputePalette fetches a backdrop's small variant through the artwork cache and derives its corner colours.

func PaletteFromImage

func PaletteFromImage(img image.Image) (Palette, error)

PaletteFromImage averages each quadrant of img and tones the averages like PMS's UltraBlur palette.

type PaletteCache

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

func NewPaletteCache

func NewPaletteCache(db *sql.DB, submit func(string, func(context.Context)) bool, now func() time.Time, log *slog.Logger, compute func(context.Context, core.RatingKey, string) (Palette, error)) *PaletteCache

func (*PaletteCache) Lookup

func (c *PaletteCache) Lookup(key core.RatingKey, path string) *Palette

lookup returns the colours of key's backdrop path, or nil when they are not known yet (scheduling their computation).

func (*PaletteCache) Preload

func (c *PaletteCache) Preload(ctx context.Context, wants []PaletteWant)

preload fills the memory cache from the database for items it doesn't hold yet, in one query, so a restart doesn't recompute anything and a listing's first render already has colours computed earlier.

type PaletteWant

type PaletteWant struct {
	Key  core.RatingKey
	Path string
}

ultraBlurWant is one item a listing is about to render.

type Queue

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

Queue runs keyed background jobs on a fixed set of workers. A key that is already queued or running is not queued again, and jobs that don't fit the queue are dropped (the caller simply asks again on a later request), so a burst of listings can never pile up unbounded work or block a response.

func NewQueue

func NewQueue(ctx context.Context, wg *sync.WaitGroup, workers, depth int) *Queue

NewQueue starts workers that stop when ctx is cancelled; wg tracks them.

func (*Queue) Submit

func (q *Queue) Submit(key string, run func(ctx context.Context)) bool

submit queues run under key. It reports whether the job was queued (false when the key is already pending, the queue is full or the server is shutting down).

func (*Queue) Wait

func (q *Queue) Wait()

wait blocks until nothing is queued or running (or the queue is shut down). Tests use it to make background enrichment deterministic.

type RemoteCache

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

func NewRemoteCache

func NewRemoteCache(budget int64, client *http.Client) *RemoteCache

func (*RemoteCache) Get

func (c *RemoteCache) Get(ctx context.Context, u string, now time.Time) (*RemoteImage, error)

get returns the image at u, fetching it once for concurrent callers.

type RemoteImage

type RemoteImage struct {
	URL         string
	Data        []byte
	ContentType string
	FetchedAt   time.Time
}

type Source

type Source struct {
	Catalog          core.StoredTitleLookup
	CollectionDevice string
	Collections      core.Collections
	Playlists        core.Playlists
	Visibility       experience.Visibility
	LiveTV           interface {
		AllowedChannels(context.Context, *core.User) ([]livetv.Channel, error)
	}
	Discovery *discovery.Features
	Images    *RemoteCache
	ImageURL  core.ImageURLFunc
	Palettes  *PaletteCache
	Now       func() time.Time
	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
	Collages *LibraryCollageCache
	// contains filtered or unexported fields
}

Source has no protocol server or protocol wire model dependencies.

func (Source) ArtPath

func (s Source) ArtPath(ctx context.Context, req frontend.ArtworkRequest, element string) (path string, defWidth int, err error)

func (*Source) BindMetadata

func (a *Source) BindMetadata(q *MetadataQueue)

BindMetadata keeps the queue so fixture ingest can store hashes before a page is served.

func (Source) ChannelImage

func (a Source) ChannelImage(viewer *core.Viewer, channel livetv.Channel) frontend.Image

ChannelImage describes a channel already filtered through AllowedChannels. The reference is not an authorization credential; List rechecks policy.

func (Source) LibraryCollage

func (a Source) LibraryCollage(ctx context.Context, viewer *core.User, _ core.Device, viewID string, children []core.Title) (frontend.Image, error)

LibraryCollage builds a square tile of the first few visible child posters. It is a generated image, not one child's poster. An empty selection is an error.

func (Source) List

func (Source) ListPage

func (a Source) ListPage(ctx context.Context, viewer *core.Viewer, device core.Device, titles []core.Title) (map[core.RatingKey][]frontend.Image, error)

ListPage lists artwork for titles already loaded by the caller. Overlay settings and saved variants are read once for the page.

func (Source) PersonImages

func (a Source) PersonImages(ctx context.Context, req frontend.ArtworkRequest, title core.Title) ([]frontend.Image, error)

PersonImages consumes an already-authorized detached title. It deliberately bypasses StoredTitle and all variant/metadata queues.

func (Source) Read

Read re-enumerates under current policy and descriptors before touching bytes.

func (*Source) StoreMetadata

func (a *Source) StoreMetadata(ctx context.Context, viewer *core.User, titles []core.Title) error

StoreMetadata hashes each title's images and waits until those rows are stored. A later page joins the rows and does not wait on the hash.

func (Source) Warm

func (a Source) Warm(title core.Title, device core.Device)

Warm schedules the cache-only variant source for a visible row or grid item.

type VariantsQueue

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

VariantsQueue keeps item enrichment cache-only. Bounded workers fills missing TMDB responses and coalesces concurrent requests per item and language. It stops when the frontend runtime's context is cancelled.

func NewVariantsQueue

func NewVariantsQueue(ctx context.Context, cached func(*core.Title, string) (*tmdb.Images, bool), fetch func(context.Context, *core.Title, string) (*tmdb.Images, error)) *VariantsQueue

func (*VariantsQueue) Get

func (q *VariantsQueue) Get(title *core.Title, language string) (*tmdb.Images, bool)

func (*VariantsQueue) Wait

func (q *VariantsQueue) Wait()

Wait joins workers after the owning context is cancelled.

Jump to

Keyboard shortcuts

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