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
- Variables
- func ComposeMediaItem(ctx context.Context, mediaDB database.MediaDBI, systemID, path string) (database.DeckItem, error)
- func DeckTagRef(deckID string) database.MediaTagRef
- func DeckURI(deckID string) string
- func ParseDeckURI(arg string) (string, bool)
- func ParseTitleLaunch(script string) (system *systemdefs.System, gameName string, ok bool)
- func PlaylistID(deck *database.Deck) string
- func ProjectDeck(ctx context.Context, deps *ResolveDeps, deckID string) (relinked int, err error)
- func StoreFetchedDeck(db *database.Database, sourceURL string, arg *PlaylistArg) (string, error)
- func TitleLaunchScript(systemID, name string, tags []database.TagInfo) string
- type PlaylistArg
- type PlaylistArgItem
- type PlaylistItem
- type ResolveDeps
- type Tagger
Constants ¶
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 ¶
var ErrMediaNotIndexed = errors.New("media is not indexed")
ErrMediaNotIndexed reports a path the media database does not hold.
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 ParseDeckURI ¶
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 ¶
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 ¶
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 ¶
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 ¶
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 ¶
PlaylistArgItem is one item of a playlist argument.
type PlaylistItem ¶
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 ¶
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 ¶
QueueDeckTags schedules the tags of the given decks.