decks

package
v2.18.0-beta.2 Latest Latest
Warning

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

Go to latest
Published: Sep 22, 2026 License: GPL-3.0 Imports: 20 Imported by: 0

Documentation

Overview

Package decks holds the local deck feature: composing deck items from indexed media and, later, projecting deck membership into the media database and opening decks as playlists. It must not import pkg/zapscript.

Index

Constants

View Source
const (
	// URIScheme names a local deck in a playlist command:
	// **playlist.open:deck://<id>.
	URIScheme = "deck"
	// MaxFetchedDecks bounds how many decks kept from links a device holds.
	// Any link that serves a playlist is kept, so the bound is what stops
	// taps piling decks up without end; the ones fetched longest ago go
	// first.
	MaxFetchedDecks = 200
)

Variables

View Source
var ErrMediaNotIndexed = errors.New("media is not indexed")

ErrMediaNotIndexed reports a path the media database does not hold.

View Source
var ErrNoUserDB = errors.New("no user database")

ErrNoUserDB reports a deck store reached with no user database open.

Functions

func ComposeMediaItem

func ComposeMediaItem(
	ctx context.Context, mediaDB database.MediaDBI, systemID, path string,
) (database.DeckItem, error)

ComposeMediaItem builds the deck item for an indexed file: a script item carrying the title launch other devices resolve through their own index, and the anchor to the exact file so this device launches what was picked and the row can be re-linked after the media database is rebuilt.

func DeckTagRef

func DeckTagRef(deckID string) database.MediaTagRef

DeckTagRef is the media tag that marks membership of one deck.

func DeckURI

func DeckURI(deckID string) string

DeckURI returns the playlist argument that opens a deck.

func ParseDeckURI

func ParseDeckURI(arg string) (string, bool)

ParseDeckURI returns the deck ID a deck:// playlist argument names.

func ParseTitleLaunch

func ParseTitleLaunch(script string) (system *systemdefs.System, gameName string, ok bool)

ParseTitleLaunch returns the system and title (with any inline tags) a script names when the script is a single launch.title command.

func PlaylistID

func PlaylistID(deck *database.Deck) string

PlaylistID returns the ID a deck opens as. A deck kept from a link opens as the playlist ID its source served, so the local copy and the served playlist are one playlist; any other deck opens as its own deck:// URI.

func ProjectDeck

func ProjectDeck(ctx context.Context, deps *ResolveDeps, deckID string) (relinked int, err error)

ProjectDeck makes the media carrying a deck's membership tag match the deck as it is stored when the projection runs: exactly the files its game items resolve to, or none when the deck no longer exists. Items that resolved by title because their file is gone are linked to the file they matched, and the number of such items is returned. Projections run one at a time and each reads the deck itself, so a projection can never write the membership of an older copy of the deck over a newer one.

func StoreFetchedDeck

func StoreFetchedDeck(db *database.Database, sourceURL string, arg *PlaylistArg) (string, error)

StoreFetchedDeck keeps a playlist served through a ZapLink as a read-only deck and returns the deck's ID on this device. The copy is known by the link it came from and nothing else, so it never stands in for, or is hidden by, a deck the user owns. Every served entry becomes a script item: a card with several scripts is served as a nested playlist command and is kept as that script. A deck that changed has its membership tags queued, so the tags and the files its items link to follow the fetch in the background.

func TitleLaunchScript

func TitleLaunchScript(systemID, name string, tags []database.TagInfo) string

TitleLaunchScript renders the explicit title launch for a game: **launch.title:<System>/<Title> (type:value)... The tags are the title's disambiguating tags, which always include the ones that make the file a distinct game, so the script names this game on any device. The argument is written through the ZapScript serializer, so a title holding a character the parser treats specially (a question mark, a comma between grouped tag values, a pipe) is quoted and survives as one argument.

Types

type PlaylistArg

type PlaylistArg struct {
	ID    string            `json:"id"`
	Name  string            `json:"name"`
	Items []PlaylistArgItem `json:"items"`
}

PlaylistArg is the JSON argument of a playlist command.

func ParseServedPlaylist

func ParseServedPlaylist(body string) (zapscript.Command, PlaylistArg, bool)

ParseServedPlaylist reads a fetched ZapLink body as a playlist to keep: one playlist.open, playlist.play or playlist.load command whose only argument is a JSON playlist with at least one item to run. It returns the command as served and its playlist. What the link looks like and what the playlist calls itself play no part, so every host's playlist is kept alike.

type PlaylistArgItem

type PlaylistArgItem struct {
	Name      string `json:"name"`
	ZapScript string `json:"zapscript"`
}

PlaylistArgItem is one item of a playlist argument.

type PlaylistItem

type PlaylistItem struct {
	Name      string
	ZapScript string
}

PlaylistItem is one entry of a deck as a playlist runs it.

func PlaylistItems

func PlaylistItems(ctx context.Context, mediaDB database.MediaDBI, deck *database.Deck) []PlaylistItem

PlaylistItems turns a deck into the entries a playlist runs. A game item whose linked file is still indexed launches that exact file, so the pick made on this device is what plays; any other game item runs its title launch. A card item runs its script, or opens its scripts as a nested playlist when it has several, the way the card's own link does.

type ResolveDeps

type ResolveDeps struct {
	MediaDB database.MediaDBI
	UserDB  database.UserDBI
	Cfg     *config.Instance
	// LaunchersForSystem returns the launchers used to rank title matches,
	// the same set a title launch ranks with.
	LaunchersForSystem func(systemID string) []platforms.Launcher
}

ResolveDeps carries what resolving deck items to local media needs.

type Tagger

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

Tagger keeps deck membership tags in the media database in step with the decks in the user database. Deck edits and reindexes queue work and return at once, and one worker brings each queued deck's tags up to date. A deck whose games this device does not have costs a title lookup per item on every pass, so doing this inside an edit would hold up the edit and every browse behind it. The queue is saved in the user database, so work queued before a restart is finished after it.

func NewTagger

func NewTagger(deps *ResolveDeps, onRelinked func(deckID string)) *Tagger

NewTagger returns a tagger holding any work a previous run left queued. onRelinked, when set, is called after items of a deck were linked to the files their titles matched.

func (*Tagger) Drain

func (t *Tagger) Drain(ctx context.Context) (failed bool)

Drain brings every queued deck's tags up to date, one deck at a time, and returns when the queue is empty or ctx ends. It waits while an index, optimization, recovery or maintenance job owns the media database: those hold long write transactions a tag write would time out behind, and a finished index queues every deck anyway. A deck that fails stays queued and is not tried again in this call; Drain reports whether any did.

func (*Tagger) QueueAllDeckTags

func (t *Tagger) QueueAllDeckTags()

QueueAllDeckTags schedules every deck's tags and the removal of tags that belong to no deck.

func (*Tagger) QueueDeckTags

func (t *Tagger) QueueDeckTags(deckIDs ...string)

QueueDeckTags schedules the tags of the given decks.

func (*Tagger) Run

func (t *Tagger) Run(ctx context.Context)

Run works through the queue until ctx ends, starting with anything an earlier run left queued. It runs at background priority on its own thread.

Jump to

Keyboard shortcuts

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