platforms

package
v2.19.0 Latest Latest
Warning

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

Go to latest
Published: Oct 2, 2026 License: GPL-3.0 Imports: 34 Imported by: 0

Documentation

Index

Constants

View Source
const (
	// LaunchRepairParamLauncher names the launcher application, such as "RetroArch".
	LaunchRepairParamLauncher = "launcher"
	// LaunchRepairParamPlugin names the launcher's plugin or core, such as "Mesen".
	LaunchRepairParamPlugin = "plugin"
)

Parameter names a repair error may carry. The key set is closed: these are display names a client substitutes into its own wording, never identifiers, paths or host text.

View Source
const (
	ControlSaveState   = "save_state"
	ControlLoadState   = "load_state"
	ControlSaveRAM     = "save_ram"
	ControlToggleMenu  = "toggle_menu"
	ControlSave        = "save"
	ControlLoad        = "load"
	ControlReset       = "reset"
	ControlTogglePause = "toggle_pause"
	ControlPause       = "pause"
	ControlResume      = "resume"
	ControlStop        = "stop"
	ControlFastForward = "fast_forward"
	ControlRewind      = "rewind"
	ControlNext        = "next"
	ControlPrevious    = "previous"
	ControlToggleTray  = "toggle_tray"
)

Control action identifiers for active media control.

View Source
const (
	ProfileItemOwnerProfile = "profile"
	ProfileItemOwnerDevice  = "device"
	ProfileItemOwnerShared  = "shared"
)

ProfileItem owner classes. "profile" data swaps with the active profile, "device" data never swaps (it belongs to the hardware/display), and "shared" data is ambiguous by default and needs an explicit user choice before it would ever swap.

View Source
const (
	// InstanceKodi identifies launchers that send commands to a running Kodi instance
	InstanceKodi = "kodi"
)

Running instance identifiers for launchers that communicate with persistent applications. Used in Launcher.UsesRunningInstance to indicate which app instance the launcher targets.

View Source
const NativeAudioLauncherID = "native-audio"
View Source
const SourceScheme = "source"

SourceScheme is the virtual path scheme of media in a source root: a media folder a host application granted to Core, which Core cannot open through the operating system. A path in one is source://<root id>/<dir>/.../<file>, the multi-segment virtual path form (see virtualpath.CreateVirtualPathSegments).

View Source
const (
	// SystemMenu identifies the platform's main menu/frontend target.
	SystemMenu = "menu"
)

System identifiers for platform-level targets.

Variables

View Source
var ErrNotSourcePath = errors.New("not a source root path")

ErrNotSourcePath reports a path that is not a source root or a path below one.

View Source
var ErrNotSupported = errors.New("operation not supported on this platform")
View Source
var ErrProfileDataUnavailable = errors.New("profile data swap unavailable")

ErrProfileDataUnavailable is returned (wrapped) by ApplyProfile when the swap cannot run on the current storage setup — e.g. saves are on a read-only network mount — as opposed to an operation failing. Callers report it as "unavailable" rather than "failed".

View Source
var ErrScannerUnavailable = errors.New("optional scanner source is unavailable")

ErrScannerUnavailable identifies an absent optional scanner source, not a configuration or I/O failure. Scanning remains incomplete so existing media is preserved. Return this directly, without joining it with another failure.

View Source
var ErrScriptAlreadyRunning = errors.New("a script is already running")

ErrScriptAlreadyRunning reports a script launch refused because the platform's script runner is occupied. The caller must still receive the refusal.

View Source
var ErrStopFailed = errors.New("failed to stop active launcher")

ErrStopFailed reports that a stop was attempted and did not succeed: the media is still running. Callers must not treat the media as stopped, and platforms returning it must leave active media in place so Core's state keeps matching reality.

Functions

func DoLaunch added in v2.8.0

func DoLaunch(params *LaunchParams, getDisplayName func(string) string) error

DoLaunch launches the given path and updates the active media with it if it was successful. The getDisplayName callback extracts a display name from the path.

func IsActionDetails added in v2.8.0

func IsActionDetails(action string) bool

IsActionDetails returns true if action is "details" (case-insensitive).

func IsSourcePath added in v2.19.0

func IsSourcePath(path string) bool

IsSourcePath reports whether path is a source root or a path below one.

func IsSourceScheme added in v2.19.0

func IsSourceScheme(path string) bool

IsSourceScheme reports whether path is the bare source scheme or any path under it - unlike IsSourcePath, which requires a root id (a genuine reference), this also matches the bare scheme itself. media.browse's root discovery (BrowseVirtualSchemes) collapses every granted source root into one shared "source://" route the same way it already does for a flat virtual scheme, so the browse API needs to recognize that bare bucket as its own browsable path - an aggregated view across every granted root, not a reference to any one of them.

func KeyboardControls added in v2.10.0

func KeyboardControls(pl Platform, actions map[string]string) map[string]Control

KeyboardControls builds a Controls map from action→key mappings using the platform's KeyboardPress method. Key strings use the standard zapscript input format (e.g., "a", "{f9}", "{ctrl+q}").

func LaunchRepairParams added in v2.19.0

func LaunchRepairParams() []string

LaunchRepairParams returns every parameter name in the closed key set.

func NewLaunchRepairError added in v2.19.0

func NewLaunchRepairError(message string) error

NewLaunchRepairError must never receive paths, scripts, credentials, provider errors or other runtime input. Use fixed messages selected by a bounded code. It reports LaunchRepairUnspecified, for producers that have no code yet.

func NewLaunchRepairErrorWithReason added in v2.19.0

func NewLaunchRepairErrorWithReason(
	reason LaunchRepairReason,
	params map[string]string,
	message string,
) error

NewLaunchRepairErrorWithReason builds the client-facing repair error. A reason outside the closed set becomes LaunchRepairUnspecified, an unusable message becomes the generic fallback, and a parameter outside the closed key set or not shaped like a display name is dropped rather than sent.

func PowerStatus added in v2.17.0

func PowerStatus(pl Platform) power.Status

PowerStatus reports where pl is drawing power from, preferring the platform's own reading when it has one.

A reading that fails is reported as unknown rather than as an error the caller has to interpret: whether the battery is unreadable or the call itself broke, what the caller can do about it is the same.

func ResolveAction added in v2.8.0

func ResolveAction(opts *LaunchOptions, cfg *config.Instance, launcher *Launcher) string

ResolveAction returns the effective action for a launch, checking: 1. Explicit action from LaunchOptions (from advargs) 2. Config default for the launcher 3. Empty string (default "run" behavior)

func SourceLocation added in v2.19.0

func SourceLocation(path string) (id string, segments []string, err error)

SourceLocation splits a source root, or a path below one, into the root's ID and the decoded segments below it. A root has no segments. A path below a root must be in its canonical form.

func SourceRootPath added in v2.19.0

func SourceRootPath(reference string) string

SourceRootPath returns the path of the source root the host knows as reference, source://<id>. The ID is a hash of the reference, so it is stable for as long as the host keeps the same reference, including after access is lost and granted again, and it reveals nothing of the reference.

Types

type BackupDefinition added in v2.16.0

type BackupDefinition struct {
	SourceRoot  string
	RestoreRoot string
	// RestoreTargetRoot optionally maps RestoreRoot to a platform-discovered
	// physical category root. It must never be derived from backup contents.
	RestoreTargetRoot  string
	Category           string
	Include            []BackupPattern
	Exclude            []BackupPattern
	SourceTrustedRoots []string
	NonRecursive       bool
}

type BackupPattern added in v2.16.0

type BackupPattern struct {
	Glob     string
	Contains string
	All      bool
}

type BackupPlan added in v2.16.0

type BackupPlan struct {
	Definitions []BackupDefinition
	Warnings    []BackupWarning
}

type BackupPlanningProvider added in v2.16.0

type BackupPlanningProvider interface {
	BackupPlan() BackupPlan
}

type BackupPreparingProvider added in v2.17.0

type BackupPreparingProvider interface {
	// PrepareBackup returns a non-nil, idempotent cleanup callback on success.
	// When it returns an error, cleanup is nil and must not be called.
	PrepareBackup() (BackupPlan, func() error, error)
}

type BackupProvider added in v2.16.0

type BackupProvider interface {
	BackupDefinitions() []BackupDefinition
}

type BackupRestorePreparer added in v2.16.0

type BackupRestorePreparer interface {
	PrepareBackupRestore() (func(bool) error, error)
}

type BackupRestoreRootProvider added in v2.16.0

type BackupRestoreRootProvider interface {
	BackupRestoreRoot() string
}

type BackupWarning added in v2.16.0

type BackupWarning struct {
	Category string
	Path     string
	Reason   string
}

type CmdEnv

type CmdEnv struct {
	// LauncherCtx is canceled when a new launcher starts and replaces the current one.
	LauncherCtx context.Context
	// ServiceCtx is canceled during full service shutdown or process stop. Use it
	// for work tied to service lifetime rather than the current launcher lifetime.
	ServiceCtx         context.Context
	WaitForMediaReady  func(context.Context) error
	AcquireMediaLaunch func() (MediaLaunchAccess, error)
	SkipMediaLaunch    func(ResolvedLaunch) bool
	PrepareMediaLaunch func(ResolvedLaunch) (bool, error)
	AcquireLaunch      func() (func(), error)
	// LaunchInProgress reports whether another launch holds the exclusive
	// launch lock. Nil when there is no launcher manager to ask.
	LaunchInProgress func() bool
	// BeforeExit runs the outgoing media's before_exit script. The launch path
	// calls it once the replacement has been resolved but before it takes the
	// media launch gate, so a launch that never happens cannot fire it and the
	// script is still free to run its own ZapScript. Nil when the hook must not
	// run, such as inside a hook script.
	BeforeExit func()
	// RefreshOwnedDeck asks wherever an owned deck syncs to look for changes
	// in the background as the deck opens. It returns at once and never
	// blocks the open; nil when no sync is configured.
	RefreshOwnedDeck func(ctx context.Context, deckID string)
	PlaybackManager  audio.PlaybackManager
	// LauncherCache resolves the launcher behind the active media. It holds
	// launchers the platform cannot build itself, so it is the only complete
	// source; never resolve a launcher ID from Platform.Launchers alone.
	LauncherCache LauncherResolver
	// Launchers memoises Platform.Launchers for this command. Nil asks the
	// platform each time.
	Launchers *LauncherSnapshot
	UI        *uievents.Service
	Playlist  playlists.PlaylistController
	// AllowedCommands is the bound the running token carries. It is forwarded
	// so a playlist opened by this command keeps the same bound, the way
	// Unsafe does.
	AllowedCommands tokens.CommandPolicy
	Cfg             *config.Instance
	Database        *database.Database
	ExprEnv         *zapscript.ArgExprEnv
	Source          string
	// PathRoot is an optional per-token root for resolving relative filesystem paths.
	PathRoot      string
	Cmd           zapscript.Command
	TotalCommands int
	CurrentIndex  int
	Unsafe        bool
}

CmdEnv is the local state of a scanned token, as it processes each ZapScript command. Every command run has access to and can modify it.

type CmdResult

type CmdResult struct {
	// Playlist is the result of the playlist change.
	Playlist *playlists.Playlist
	// ProfileSwitch requests the active profile be changed. Commands return
	// the request as intent; the service layer applies it (same pattern as
	// Playlist). The scan path activates without a PIN check — possession
	// of the card is the authorization.
	ProfileSwitch *ProfileSwitchRequest
	// PlaytimeExtension requests extra time for the current playtime
	// session. Like ProfileSwitch this is intent only: the service layer
	// verifies the authorizing credential and applies the grant.
	PlaytimeExtension *PlaytimeExtensionRequest
	// Strategy indicates which matching strategy was used for title-based launches.
	// Empty for non-title commands. Used for testing and debugging title resolution.
	Strategy string
	// NewCommands instructs the script runner to prepend these additional
	// commands to the current script's remaining command list.
	NewCommands []zapscript.Command
	// Confidence is a float from 0.0 to 1.0 indicating how confident the
	// a launch command was in its media resolution.
	Confidence float64
	// MediaChanged is true if a command may have started or stopped running
	// media, and could affect handling of the hold mode feature. This doesn't
	// include playlist changes, which manage running media separately.
	MediaChanged bool
	// PlaylistChanged is true if a command started/changed/stopped a playlist.
	PlaylistChanged bool
	// Unsafe flags that a token has been generate by a remote/untrusted source
	// and can no longer be considered safe. This flag will flow on to any
	// remaining commands.
	Unsafe bool
}

CmdResult returns a summary of what global side effects may or may not have happened as a result of a single ZapScript command running.

type ConsoleManager added in v2.7.0

type ConsoleManager interface {
	// Open switches to console mode on the specified VT.
	// The provided context can be used to cancel the operation if the launcher is superseded.
	Open(ctx context.Context, vt string) error

	// Close exits console mode and returns to normal display
	Close() error

	// Clean prepares a console for use (clears screen, hides cursor)
	Clean(vt string) error

	// Restore restores console cursor state
	Restore(vt string) error
}

ConsoleManager handles platform-specific console/TTY switching operations. This is primarily used by MiSTer for video playback and script execution.

type Control added in v2.10.0

type Control struct {
	Func   ControlFunc // Native Go implementation
	Script string      // ZapScript string executed via RunControlScript
}

Control represents a single control action. Either Func (native Go for built-in launchers) or Script (zapscript string for custom launchers) should be set, not both.

type ControlFunc added in v2.10.0

type ControlFunc func(context.Context, *config.Instance, ControlParams) error

ControlFunc is a function that executes a control action on active media.

type ControlParams added in v2.10.0

type ControlParams struct {
	Args map[string]string
}

ControlParams contains parameters for a control action.

type InputSession added in v2.17.0

type InputSession interface {
	KeyboardPressSequence(context.Context, []string, time.Duration) error
	GamepadPressSequence(context.Context, []string, time.Duration) error
	ReleaseAll() error
}

InputSession owns keyboard and gamepad inputs held by one durable client connection. Implementations must isolate held input between sessions and release all owned input when ReleaseAll is called.

type InputSessionProvider added in v2.17.0

type InputSessionProvider interface {
	NewInputSession() InputSession
}

InputSessionProvider is optionally implemented by platforms that support input held across multiple API requests.

type LaunchCommand added in v2.17.0

type LaunchCommand struct {
	Executable string
	Dir        string
	Args       []string
	Env        []string
}

LaunchCommand is an executable and argument vector that can be delegated to a platform-owned process runtime without invoking a shell.

type LaunchOptions added in v2.8.0

type LaunchOptions struct {
	// ActiveMediaPublisher is the launch-scoped publication callback supplied
	// by Core. Launchers must not retain or invoke it directly.
	ActiveMediaPublisher func(*models.ActiveMedia)
	// RenderScale is the preferred internal rendering size as a percentage of
	// available output dimensions. It does not change physical display mode.
	RenderScale *int
	// Action specifies the launch action. Common values:
	// - "": Automatic behavior (may open details if media is not installed)
	// - "run": Explicitly launch/play the media
	// - "details": Show media details/info page instead of launching
	// Launchers may update Action to reflect a successful automatic redirect;
	// Core uses the effective action when deciding whether to publish ActiveMedia.
	Action string
	// RenderResolution is the preferred fixed internal rendering size in
	// WIDTHxHEIGHT form. It is mutually exclusive with RenderScale.
	RenderResolution string
	// SetName specifies a platform-defined launch profile/core name override.
	// On MiSTer this maps to the MGL <setname> tag.
	SetName string
	// SetNameSameDir is a raw optional platform-defined flag controlling whether
	// SetName should keep the original game directory. On MiSTer this maps to the
	// MGL setname same_dir attribute. Unsupported platforms may ignore it.
	SetNameSameDir string
	// Slot selects the media slot for launch routing. Empty means primary.
	Slot string
}

LaunchOptions contains optional parameters that can be passed to launchers.

type LaunchParams added in v2.8.0

type LaunchParams struct {
	// Context scopes best-effort post-launch metadata lookups.
	Context        context.Context
	Platform       Platform
	Config         *config.Instance
	SetActiveMedia func(*models.ActiveMedia)
	Launcher       *Launcher
	DB             *database.Database
	Options        *LaunchOptions
	Path           string
}

LaunchParams contains all dependencies required for launching media.

type LaunchPathNormalizer added in v2.18.0

type LaunchPathNormalizer interface {
	NormalizeLaunchPath(string) string
}

LaunchPathNormalizer resolves platform-specific launch aliases before comparing a requested target with active media. It must not start or stop media.

type LaunchRepairError added in v2.19.0

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

LaunchRepairError explicitly marks a launch failure as one a client may show. The reason and parameters are the contract; the message is a fixed English fallback kept for clients that only read error.message. Wrapping error details remain private to Core logs.

func (*LaunchRepairError) Error added in v2.19.0

func (e *LaunchRepairError) Error() string

func (*LaunchRepairError) Params added in v2.19.0

func (e *LaunchRepairError) Params() map[string]string

Params returns a copy of the bounded display names, or nil when there are none, so a client-facing payload cannot be edited through the error.

func (*LaunchRepairError) Reason added in v2.19.0

Reason is never empty: an error built without a usable one reports LaunchRepairUnspecified, which tells a client to show the message as it is.

type LaunchRepairReason added in v2.19.0

type LaunchRepairReason string

LaunchRepairReason is the closed set of reasons a launch needs the user to fix something before it can succeed. A client branches on the reason and writes its own wording and localization; the error's message is only the fallback for a client that has none.

The set is closed. Adding a value means mapping every producer onto it and documenting it in docs/api/methods.md in the same change.

const (
	// LaunchRepairLauncherNotInstalled means the launcher application is not installed.
	LaunchRepairLauncherNotInstalled LaunchRepairReason = "launcher_not_installed"
	// LaunchRepairLauncherComponentMissing means the launcher is installed but the
	// entry point it declares is gone or disabled.
	LaunchRepairLauncherComponentMissing LaunchRepairReason = "launcher_component_missing"
	// LaunchRepairLauncherPluginMissing means the launcher is installed but its
	// plugin or core for this system is absent.
	LaunchRepairLauncherPluginMissing LaunchRepairReason = "launcher_plugin_missing"
	// LaunchRepairLauncherVersionUnsupported means the installed build of the
	// launcher cannot be used for this media, for example because its storage
	// model is unsupported. The user needs a different build of that launcher.
	LaunchRepairLauncherVersionUnsupported LaunchRepairReason = "launcher_version_unsupported"
	// LaunchRepairLauncherAmbiguous means several launchers are usable and no
	// reviewed default applies, so the user must choose one. It is reserved: no
	// producer emits it yet, because launcher selection resolves by catalog
	// precedence without asking.
	LaunchRepairLauncherAmbiguous LaunchRepairReason = "launcher_ambiguous"
	// LaunchRepairLauncherUnsupportedMedia means this launcher cannot play the
	// selected media entry.
	LaunchRepairLauncherUnsupportedMedia LaunchRepairReason = "launcher_unsupported_media"
	// LaunchRepairLauncherOptionsUnsupported means the launch options requested are
	// not supported by this launcher.
	LaunchRepairLauncherOptionsUnsupported LaunchRepairReason = "launcher_options_unsupported"
	// LaunchRepairStoragePermissionRequired means the launcher lacks the storage
	// permission it needs.
	LaunchRepairStoragePermissionRequired LaunchRepairReason = "storage_permission_required"
	// LaunchRepairStorageProviderUnsupported means the media lives on a provider
	// this launcher cannot read.
	LaunchRepairStorageProviderUnsupported LaunchRepairReason = "storage_provider_unsupported"
	// LaunchRepairStorageUnavailable means the storage holding the media is not present.
	LaunchRepairStorageUnavailable LaunchRepairReason = "storage_unavailable"
	// LaunchRepairMediaUnavailable means the media file cannot be resolved or opened.
	LaunchRepairMediaUnavailable LaunchRepairReason = "media_unavailable"
	// LaunchRepairMediaAccessRevoked means the host's access to this media's
	// source was revoked or withdrawn, distinct from LaunchRepairMediaUnavailable's
	// unspecified cause: the user can act on this one by re-granting access.
	LaunchRepairMediaAccessRevoked LaunchRepairReason = "media_access_revoked"
	// LaunchRepairHostUnavailable means the host's launch service is not answering.
	LaunchRepairHostUnavailable LaunchRepairReason = "host_unavailable"
	// LaunchRepairHostForegroundRequired means the launch needs the user to return
	// to the app first.
	LaunchRepairHostForegroundRequired LaunchRepairReason = "host_foreground_required"
	// LaunchRepairCancelled means the launch was cancelled before it started.
	LaunchRepairCancelled LaunchRepairReason = "cancelled"
	// LaunchRepairOutcomeUnknown means the launch was dispatched but its result
	// could not be confirmed.
	LaunchRepairOutcomeUnknown LaunchRepairReason = "outcome_unknown"
	// LaunchRepairRefused means the operating system refused the request. It is
	// not a catch-all: a producer that cannot say that much reports
	// LaunchRepairUnspecified instead.
	LaunchRepairRefused LaunchRepairReason = "refused"
	// LaunchRepairUnspecified means the producer sent no structured reason, so a
	// client shows the error's message verbatim. It is the default for a producer
	// with no code yet and for any reason this build does not recognise.
	LaunchRepairUnspecified LaunchRepairReason = "unspecified"
)

func LaunchRepairReasons added in v2.19.0

func LaunchRepairReasons() []LaunchRepairReason

LaunchRepairReasons returns every reason in the closed set.

func (LaunchRepairReason) Valid added in v2.19.0

func (r LaunchRepairReason) Valid() bool

Valid reports whether r belongs to the closed set.

type Launcher

type Launcher struct {
	Controls                 map[string]Control
	Scanner                  func(context.Context, *config.Instance, string, []ScanResult) ([]ScanResult, error)
	Test                     func(*config.Instance, string) bool
	Availability             func(*config.Instance) error
	Preflight                func(*config.Instance, string, *LaunchOptions) error
	Kill                     func(*config.Instance) error
	Launch                   func(*config.Instance, string, *LaunchOptions) (*os.Process, error)
	BuildLaunchCommand       func(*config.Instance, string, *LaunchOptions) (*LaunchCommand, error)
	WaitForReady             func(context.Context, *config.Instance, *models.ActiveMedia) error
	ID                       string
	SystemID                 string
	UsesRunningInstance      string
	AvailabilityReason       string
	Detected                 *bool
	Folders                  []string
	Groups                   []string
	Extensions               []string
	ScanExcludes             []string
	ScanDirectoryExcludes    []string
	Schemes                  []string
	Lifecycle                LauncherLifecycle
	SupportsDetails          bool
	AllowListOnly            bool
	SkipFilesystemScan       bool
	ScanSkipInternalSymlinks bool
	ScanOnly                 bool
	Available                bool
}

Launcher defines how a platform launcher can launch media and what media it supports launching.

func NativeAudioLauncher added in v2.15.0

func NativeAudioLauncher(
	playback audio.PlaybackManager,
	setBackgroundMedia func(*models.ActiveMedia),
	stopPrimaryMedia func(ctx context.Context, stop func() error) error,
) Launcher

NativeAudioLauncher returns the launcher that plays audio files in-process via the shared malgo output device. Playback and the media state hooks are injected so the launcher carries no package-level globals. stopPrimaryMedia wraps an explicit stop of the primary slot: native audio has no OS process, so no platform tracker notices the stop and the drain callback only fires for tracks that end on their own, which leaves the service to run the stop it is handed and clear the active media around it.

type LauncherContextManager added in v2.7.0

type LauncherContextManager interface {
	// GetContext returns the current launcher context
	GetContext() context.Context
	// NewContext cancels the current context and creates a new one
	NewContext() context.Context
}

LauncherContextManager manages launcher lifecycle contexts. When a new launcher starts, it creates a new context and cancels the old one, allowing previous launcher cleanup routines to detect they've been superseded.

type LauncherLifecycle added in v2.6.1

type LauncherLifecycle int

LauncherLifecycle determines how a launcher process is managed

const (
	// LifecycleFireAndForget (zero value) launches without tracking
	LifecycleFireAndForget LauncherLifecycle = iota
	// LifecycleTracked launches and keeps process handle for stopping
	LifecycleTracked
	// LifecycleBlocking waits for process to exit naturally
	LifecycleBlocking
	// LifecycleExternal launches without a process handle; platform lifecycle tracking publishes ActiveMedia.
	LifecycleExternal
)

type LauncherRefreshProvider added in v2.16.0

type LauncherRefreshProvider interface {
	RefreshLauncherDependencies() error
}

LauncherRefreshProvider is optionally implemented by platforms that cache runtime launcher dependencies and can force their rediscovery.

type LauncherResolver added in v2.17.1

type LauncherResolver interface {
	GetLauncherByID(id string) *Launcher
}

LauncherResolver looks up a launcher by its unique ID. Implementations cover launchers a platform cannot construct on its own, such as native audio, which needs the playback manager injected at service startup.

type LauncherRuntimeProvider added in v2.17.0

type LauncherRuntimeProvider interface {
	LauncherRuntime(cfg *config.Instance, l *Launcher) models.LauncherRuntime
}

LauncherRuntimeProvider is optionally implemented by platforms that can describe what a launcher actually runs — an FPGA core, a libretro core, an executable. Implementations must be read-only and cheap: they are called once per launcher per request and must not touch the filesystem or trigger a rescan. A zero models.LauncherRuntime means the platform has nothing to say about that launcher.

type LauncherSnapshot added in v2.19.0

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

LauncherSnapshot holds one Platform.Launchers result for the duration of a command, so resolving a launch asks the platform once however many lookups it makes. It is fresh per command: a host whose launcher list changes is asked again on the next command. The zero value is ready to use; a nil snapshot calls Platform.Launchers every time.

func (*LauncherSnapshot) Get added in v2.19.0

func (s *LauncherSnapshot) Get(pl Platform, cfg *config.Instance) []Launcher

Get returns the snapshot's launchers, asking pl on first use.

type MediaHistoryHooks added in v2.19.0

type MediaHistoryHooks struct {
	// ActiveProfileID returns the profile a launch is attributed to, or "".
	ActiveProfileID func() string
	// Changed tells API clients to refetch history. It never blocks.
	Changed func()
}

MediaHistoryHooks gives a platform that writes play history itself what the service's own active-media tracker uses for its own rows.

type MediaHistoryRecorder added in v2.19.0

type MediaHistoryRecorder interface {
	SetMediaHistoryHooks(MediaHistoryHooks)
}

MediaHistoryRecorder is implemented by a platform whose launchers are LifecycleExternal and so write play history themselves - from host foreground evidence, or a bounded host-return estimate - instead of through the service's active-media tracker. The service sets the hooks before StartPost.

type MediaLaunchAccess added in v2.17.0

type MediaLaunchAccess struct {
	SetActiveMedia func(*models.ActiveMedia)
	Release        func()
}

MediaLaunchAccess is the state publication capability held for one launch. Release must be called after LaunchMedia returns.

type MediaReadyPlatform added in v2.14.0

type MediaReadyPlatform interface {
	WaitForMediaReady(context.Context, *config.Instance, *models.ActiveMedia) error
}

MediaReadyPlatform is optionally implemented by platforms that can report when active media is ready for controls or raw input.

type MediaSource added in v2.18.0

type MediaSource struct {
	Path  string
	Root  string
	Kind  MediaSourceKind
	Group string
}

MediaSource is optional local metadata provenance for virtual media. Path is a file or directory anchor beneath Root; Kind makes lookup independent of whether the configured target currently exists. Group names the game the media belongs to when several media can share one directory: media on the same directory with the same non-empty Group are variants of one game, and metadata for the directory describes all of them.

type MediaSourceKind added in v2.18.0

type MediaSourceKind string
const (
	MediaSourceFile      MediaSourceKind = "file"
	MediaSourceDirectory MediaSourceKind = "directory"
)

type NoOpConsoleManager added in v2.7.0

type NoOpConsoleManager struct{}

NoOpConsoleManager is a console manager that does nothing. Used by platforms that don't have console switching (MiSTeX, etc).

func (NoOpConsoleManager) Clean added in v2.7.0

func (NoOpConsoleManager) Clean(_ string) error

func (NoOpConsoleManager) Close added in v2.7.0

func (NoOpConsoleManager) Close() error

func (NoOpConsoleManager) Open added in v2.7.0

func (NoOpConsoleManager) Restore added in v2.7.0

func (NoOpConsoleManager) Restore(_ string) error

type Platform

type Platform interface {
	// ID returns the unique ID of this platform.
	ID() string
	// StartPre runs any necessary platform setup BEFORE the main service has
	// started running.
	StartPre(*config.Instance) error
	// StartPost runs any necessary platform setup AFTER the main service has
	// started running. The ctx is the service-scoped context: any background
	// work the platform spawns (idle-scheduled tasks, network polls, etc.)
	// should honour it so it exits promptly on shutdown. The scheduler may be
	// nil; platforms that defer work to idle should nil-check before using it.
	StartPost(
		context.Context,
		*config.Instance,
		LauncherContextManager,
		func() *models.ActiveMedia,
		func(*models.ActiveMedia),
		*database.Database,
		*idle.Scheduler,
	) error
	// Stop runs any necessary cleanup tasks before the rest of the service
	// starts shutting down.
	Stop() error
	// Settings returns all simple platform-specific settings such as paths.
	// NOTE: Some values on the Settings struct should be accessed using helper
	// functions in the utils package instead of directly. Check comments.
	Settings() Settings
	// ScanHook is run immediately AFTER a successful scan, but BEFORE it is
	// processed for launching.
	ScanHook(*tokens.Token) error
	// SupportedReaders returns a list of supported reader modules for platform.
	SupportedReaders(*config.Instance) []readers.Reader
	// RootDirs returns root folders to scan for media files, ordered from
	// highest to lowest priority. Consumers resolving duplicate relative names
	// must prefer the first matching root.
	RootDirs(*config.Instance) []string
	// StopActiveLauncher kills/exits the currently running launcher process
	// and clears the active media if it was successful.
	// intent indicates whether this is a preemption (new launcher starting)
	// or a termination (returning to menu).
	// Returns nil when nothing was running or the stop is confirmed, and an
	// error wrapping ErrStopFailed when the media is known to still be
	// running. Active media is only cleared when the stop succeeded.
	StopActiveLauncher(intent StopIntent) error
	// ReturnToMenu returns the platform to its main UI/launcher/frontend.
	// For platforms with a menu system (MiSTer OSD, EmulationStation, Steam Big Picture),
	// this launches the menu/frontend. For platforms without a menu concept, this is a no-op.
	// This is separate from StopActiveLauncher to allow optimized transitions where
	// returning to the menu is not always necessary (e.g., MGL to MGL on MiSTer).
	ReturnToMenu() error
	// SetTrackedProcess stores a process handle for lifecycle management.
	// Used by DoLaunch to track processes that can be killed later.
	SetTrackedProcess(*os.Process)
	// LaunchSystem launches a system by ID. This generally means, if a
	// platform even has the capability, attempt to launch the default or most
	// appropriate launcher for a given system, without any media loaded.
	LaunchSystem(*config.Instance, string) error
	// LaunchMedia launches some media by path and sets the active media if it
	// was successful. Pass nil for launcher to auto-detect, or a specific Launcher.
	// The opts parameter is optional and may be nil.
	LaunchMedia(*config.Instance, string, *Launcher, *database.Database, *LaunchOptions) error
	// KeyboardPress presses and then releases a single keyboard button on a
	// virtual keyboard, using a key name from the ZapScript format.
	KeyboardPress(string) error
	// GamepadPress presses and then releases a single gamepad button on a
	// virtual gamepad, using a button name from the ZapScript format.
	GamepadPress(string) error
	// Screenshot captures a screenshot of the current platform display,
	// saves it to disk, and returns the file path and raw image bytes.
	Screenshot() (*ScreenshotResult, error)
	// ForwardCmd processes a platform-specific ZapScript command.
	ForwardCmd(*CmdEnv) (CmdResult, error)
	// LookupMapping is a platform-specific method of matching a token to a
	// mapping. It takes last precedence when checking mapping sources.
	LookupMapping(*tokens.Token) (string, bool) // DEPRECATED
	// Launchers is the complete list of all launchers available on this
	// platform.
	Launchers(*config.Instance) []Launcher
	// ConsoleManager returns the platform's console manager for TTY/console switching.
	// Platforms without console switching return NoOpConsoleManager.
	ConsoleManager() ConsoleManager
	// ManagedByPackageManager returns true if this install is managed by an
	// external package manager (e.g. MiSTer Downloader, Batocera pacman).
	// Used to default auto-update off for package-managed installs.
	ManagedByPackageManager() bool
	// Scrapers returns the metadata scrapers available on this platform,
	// keyed by scraper ID. The map may be empty if no scrapers are supported.
	Scrapers(*config.Instance) map[string]Scraper
}

Platform is the central interface that defines how Core interacts with a supported platform.

type PlaytimeExtensionRequest added in v2.17.0

type PlaytimeExtensionRequest struct {
	// Mode is models.PlaytimeExtendModeDuration or ...ModeToday.
	Mode string
	// AuthorizerSwitchID is the switch ID of the authorizing profile.
	AuthorizerSwitchID string
	// Duration is the time to add, for duration mode only.
	Duration time.Duration
}

PlaytimeExtensionRequest asks the script runner to grant extra time to the session currently being limited. AuthorizerSwitchID is the bearer credential from the card; the service layer resolves it and checks the profile's role, so the command layer never sees a verified identity.

type PowerStatusProvider added in v2.17.0

type PowerStatusProvider interface {
	PowerStatus() (power.Status, error)
}

PowerStatusProvider is optionally implemented by platforms whose power state cannot be read the ordinary way. Handheld hardware with an out-of-tree battery driver is the case this exists for; platforms that leave it unimplemented are read through the kernel or OS power API instead.

type ProfileDataSwapper added in v2.16.0

type ProfileDataSwapper interface {
	// ProfileItems reports what a profile change can affect on this
	// platform.
	ProfileItems() []ProfileItem
	// ApplyProfile makes the platform's profile-scoped data current for
	// the given profile, applying only the enabled item IDs. It is called
	// only while no media is running, must be idempotent, and must leave
	// existing data intact on failure.
	ApplyProfile(ref ProfileRef, enabledItems []string) error
}

ProfileDataSwapper is an optional platform capability: platforms that can swap profile-scoped data (save files, save states) implement it and core discovers it by type assertion. Platforms without the capability simply don't implement it — profiles there are limits + attribution only.

type ProfileDataWatcher added in v2.16.0

type ProfileDataWatcher interface {
	// WatchProfileData invokes onChange (possibly from another goroutine)
	// whenever platform storage state changes, until ctx is done.
	WatchProfileData(ctx context.Context, onChange func())
}

ProfileDataWatcher is an optional platform capability: platforms whose profile data state can change underneath the service (e.g. MiSTer's mount table, where a cifs boot script or a USB drive can appear at any time) implement it so the service can re-reconcile on those changes.

type ProfileItem added in v2.16.0

type ProfileItem struct {
	ID    string // stable identity, e.g. "saves", "savestates"
	Label string // for client UI, e.g. "Save files"
	Owner string // one of the ProfileItemOwner* constants
}

ProfileItem describes one category of data a profile change can affect on a platform. It is purely descriptive: no paths, no mechanisms.

type ProfileRef added in v2.16.0

type ProfileRef struct {
	ID   string
	Name string
}

ProfileRef identifies the profile whose data should be made current. An empty ID means the shared profile (the device's un-profiled state). Name is the display name, used by platforms to label per-profile storage for humans browsing it outside Zaparoo.

type ProfileSwitchRequest added in v2.16.0

type ProfileSwitchRequest struct {
	SwitchID string
	Clear    bool
}

ProfileSwitchRequest asks the script runner to change the device's active profile. SwitchID selects a profile by its card switch ID; Clear deactivates the current profile instead.

type ResolvedLaunch added in v2.18.0

type ResolvedLaunch struct {
	Launcher *Launcher
	Options  *LaunchOptions
	Path     string
	SystemID string
}

ResolvedLaunch identifies the target after script and launcher resolution. A nil Launcher leaves launcher selection to the platform.

type ScanResult

type ScanResult struct {
	// Source is optional local metadata provenance for a virtual launch URI.
	Source *MediaSource
	// Path is the absolute path or virtual launch URI for this media.
	Path string
	// Name is the display name of the media, shown to the users and used for
	// search queries.
	Name string
	// NoExt indicates this is a virtual path with no file extension.
	// When true, filepath.Ext() extraction is skipped to avoid extracting
	// garbage from paths like "/games/file.txt/Game (v1.0)" or "kodi://123/Dr. Strange".
	NoExt bool
}

ScanResult is a result generated from a media database indexing files or other media sources.

type Scraper added in v2.12.0

type Scraper struct {
	CustomOpts ScraperCustomOptions
	Scrape     func(
		ctx context.Context,
		cfg *config.Instance,
		pl Platform,
		fs afero.Fs,
		db *database.Database,
		opts scraper.ScrapeOptions,
		custom ScraperCustomOptions,
		ch chan<- scraper.ScrapeUpdate,
	) error
	ID                 string
	Name               string
	SupportedSystemIDs []string
	// AutoScrapeLaunchers opts successful index contributions into ordinary
	// fill-missing jobs. Empty leaves this scraper manual-only.
	AutoScrapeLaunchers []string
	SupportsFillMissing bool
}

Scraper defines a metadata scraper available on a platform. Scrapers are returned lazily by Platform.Scrapers and carry their full implementation in the Scrape function field.

type ScraperCustomOption added in v2.12.0

type ScraperCustomOption struct {
	Name  string
	Value string
}

ScraperCustomOption is a single user-configurable option for a scraper.

type ScraperCustomOptions added in v2.12.0

type ScraperCustomOptions map[string][]ScraperCustomOption

ScraperCustomOptions maps option names to their available values per scraper.

type ScreenshotResult added in v2.10.0

type ScreenshotResult struct {
	// Path is the absolute path where the screenshot was saved on disk.
	Path string
	// Data is the raw image bytes of the screenshot.
	Data []byte
}

ScreenshotResult is the result of a platform screenshot capture.

type ServiceReadyPlatform added in v2.14.0

type ServiceReadyPlatform interface {
	WaitForServiceReady(context.Context, *config.Instance) error
}

ServiceReadyPlatform is optionally implemented by platforms that can report when startup-dependent platform features are ready for user hooks.

type Settings

type Settings struct {
	// DataDir returns the root folder where things like databases and
	// downloaded assets are permanently stored. WARNING: This value should be
	// accessed using the DataDir function in the utils package.
	DataDir string
	// ConfigDir returns the directory where the config file is stored.
	// WARNING: This value should be accessed using the ConfigDir function in
	// the utils package.
	ConfigDir string
	// TempDir returns a temporary directory for files used for inter-process
	// communication such as PID files and temporary binaries. Expect it to be
	// deleted.
	TempDir string
	// LogDir returns the directory where persistent log files are stored.
	LogDir string
	// HostManagedPaths makes the supplied directories authoritative instead of probing
	// for a portable user directory next to the current executable.
	HostManagedPaths bool
	// DisableSelfUpdate means the host updates this component as part of its own package.
	// Neither automatic nor manually requested executable updates may run.
	DisableSelfUpdate bool
	// ZipsAsDir returns true if this platform treats .zip files as if they
	// were directories for the purpose of launching media.
	ZipsAsDirs bool
	// DisableZapScriptInTUI prevents token scans from launching media while
	// the main TUI occupies the platform's primary display. Utility widgets do
	// not apply this policy because their controls can trigger ZapScript.
	DisableZapScriptInTUI bool
	// ResourceConstrained indicates the platform has limited CPU and I/O
	// capacity. Core uses lower-cost audio processing and cooperatively paces
	// expensive background media work on these platforms.
	ResourceConstrained bool
	// ThrottleBackground paces indexing and scraping the same way as
	// ResourceConstrained, so an interactive host keeps CPU time for its UI,
	// without the other ResourceConstrained effects (audio quality, scanner
	// walkers, import limits, thumbnail concurrency).
	ThrottleBackground bool
}

Settings defines all simple settings/configuration values available for a platform.

type SourceEntry added in v2.19.0

type SourceEntry struct {
	// Name is the entry's own name, never a path.
	Name string
	// Size is the file size in bytes, or -1 when unknown.
	Size int64
	Dir  bool
}

SourceEntry is one entry of a source root directory.

type SourceFileReader added in v2.19.0

type SourceFileReader interface {
	// ReadSourceFile returns up to limit+1 bytes of the file at path (a
	// source root path below a root, never a bare root), so a caller can
	// detect an oversized file without reading all of it.
	ReadSourceFile(ctx context.Context, path string, limit int64) ([]byte, error)
}

SourceFileReader is implemented by a platform that can also return a source root file's bytes, not just list its directories: a separate, optional capability from SourceRootReader, since returning file content needs a real read of the host's data (e.g. through Binder on Android), not just a directory listing.

type SourceRootReader added in v2.19.0

type SourceRootReader interface {
	// SourceRoots returns the source roots Core may index now, each made by
	// SourceRootPath. It is called once at the start of an index run.
	SourceRoots(ctx context.Context) ([]string, error)
	// ReadSourceDir lists one directory. path is a source root or a
	// directory below one, as a canonical multi-segment virtual path.
	ReadSourceDir(ctx context.Context, path string) ([]SourceEntry, error)
}

SourceRootReader is implemented by a platform whose media sits in source roots. Core treats a source root like a directory from RootDirs: it looks in it for the folders launchers declare, walks the matching system folders and indexes their files as source:// paths. The platform only lists and reads; it makes no decision about systems, media or identities.

Launching is the platform's own: a launcher that matches a source:// path receives it and opens it through the host.

type StopIntent added in v2.7.0

type StopIntent int

StopIntent indicates the reason for stopping a launcher

const (
	// StopForPreemption (zero value) means a new launcher is starting
	StopForPreemption StopIntent = iota
	// StopForMenu means stopping to return to menu/frontend
	StopForMenu
	// StopForConsoleReset means stopping to reset console state (video mode, etc) before new console launch
	StopForConsoleReset
)

type SystemLauncherSelector added in v2.17.0

type SystemLauncherSelector interface {
	LaunchSystemLauncher(cfg *config.Instance, systemID string, launcher *Launcher) error
}

SystemLauncherSelector is optionally implemented by platforms where a system can run under more than one launcher (e.g. a MiSTer alt core) and a caller needs to pick which one, with no media loaded. Callers must verify launcher.SystemID matches systemID before calling; implementations are not required to check it themselves.

type TrackedProcessMediaClearer added in v2.16.0

type TrackedProcessMediaClearer interface {
	ClearTrackedProcessMedia(*os.Process) bool
}

TrackedProcessMediaClearer optionally clears active media only when proc remains the process that most recently completed for the platform.

type TrackedProcessWaiter added in v2.16.0

type TrackedProcessWaiter interface {
	WaitTrackedProcess(*os.Process) error
}

TrackedProcessWaiter is optionally implemented by platforms that coordinate process waiting with StopActiveLauncher. Exactly one caller must reap a process.

type UpdatePayloadProvider added in v2.17.0

type UpdatePayloadProvider interface {
	UpdatePayload() []updatepayload.File
}

Directories

Path Synopsis
Package android is the Android platform.
Package android is the Android platform.
Package ids provides platform ID constants.
Package ids provides platform ID constants.
Package mediaslot defines media slot identifiers shared across launch, playback, and playlist routing.
Package mediaslot defines media slot identifiers shared across launch, playback, and playlist routing.
catalog
Package catalog preserves the original Core import path for the standalone github.com/ZaparooProject/zaparoo-core/mister/catalog module.
Package catalog preserves the original Core import path for the standalone github.com/ZaparooProject/zaparoo-core/mister/catalog module.
mgl
Package mgl preserves the original Core import path for the standalone github.com/ZaparooProject/zaparoo-core/mister/mgl module.
Package mgl preserves the original Core import path for the standalone github.com/ZaparooProject/zaparoo-core/mister/mgl module.
esapi
Package esapi provides types and helpers for reading EmulationStation gamelist.xml files.
Package esapi provides types and helpers for reading EmulationStation gamelist.xml files.
esde
Package esde provides shared utilities for EmulationStation Desktop Edition based platforms including ES-DE, Batocera ES, and RetroBat.
Package esde provides shared utilities for EmulationStation Desktop Edition based platforms including ES-DE, Batocera ES, and RetroBat.
esmedia
Package esmedia resolves local EmulationStation-style media folders and paths.
Package esmedia resolves local EmulationStation-style media folders and paths.
linuxbase/gamescope
Package gamescope makes externally launched windows visible and focused in gamescope Gaming Mode sessions.
Package gamescope makes externally launched windows visible and focused in gamescope Gaming Mode sessions.
linuxbase/procscanner
Package procscanner provides a shared process scanner for monitoring multiple types of processes with a single /proc scan.
Package procscanner provides a shared process scanner for monitoring multiple types of processes with a single /proc scan.
linuxbase/proctracker
Package proctracker provides process exit tracking using pidfd_open on Linux 5.3+.
Package proctracker provides process exit tracking using pidfd_open on Linux 5.3+.
linuxemu
Package linuxemu provides reusable emulator discovery and launchers for Linux-family platforms.
Package linuxemu provides reusable emulator discovery and launchers for Linux-family platforms.
pinup
Zaparoo Core Copyright (c) 2026 The Zaparoo Project Contributors.
Zaparoo Core Copyright (c) 2026 The Zaparoo Project Contributors.
retroarch
Package retroarch provides reusable RetroArch CLI launchers.
Package retroarch provides reusable RetroArch CLI launchers.
steam/steamtracker
Package steamtracker provides Steam game lifecycle tracking on Linux.
Package steamtracker provides Steam game lifecycle tracking on Linux.
Package updatepayload describes platform files shipped beside the Core binary that must stay in sync when an unmanaged install updates itself.
Package updatepayload describes platform files shipped beside the Core binary that must stay in sync when an unmanaged install updates itself.
Zaparoo Core Copyright (c) 2026 The Zaparoo Project Contributors.
Zaparoo Core Copyright (c) 2026 The Zaparoo Project Contributors.
windowfocus
Package windowfocus activates windows created by launched Windows processes.
Package windowfocus activates windows created by launched Windows processes.
Package zapos implements the Zaparoo OS appliance platform.
Package zapos implements the Zaparoo OS appliance platform.

Jump to

Keyboard shortcuts

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