Documentation
¶
Index ¶
- Constants
- Variables
- func AlphaMapKeys[V any](m map[string]V) []string
- func CachedCompile(pattern string) (*regexp.Regexp, error)
- func CachedMustCompile(pattern string) *regexp.Regexp
- func ConfigDir(pl platforms.Platform) string
- func Contains[T comparable](xs []T, x T) bool
- func CopyFile(sourcePath, destPath string, perm ...os.FileMode) error
- func DataDir(pl platforms.Platform) string
- func DecodeURIIfNeeded(uri string) string
- func DoLaunch(params *LaunchParams) error
- func EnsureDirectories(pl platforms.Platform) error
- func EqualStringSlices(a, b []string) bool
- func ExeDir() string
- func FilenameFromPath(p string) string
- func FindLauncher(cfg *config.Instance, pl platforms.Platform, path string) (platforms.Launcher, error)
- func GetAllLocalIPs() []string
- func GetFileSize(filePath string) (int64, error)
- func GetLocalIP() string
- func GetMd5Hash(filePath string) (string, error)
- func GetSerialDeviceList() ([]string, error)
- func HasUserDir() (string, bool)
- func InitLogging(pl platforms.Platform, writers []io.Writer) error
- func IsClockReliable(t time.Time) bool
- func IsFalsey(s string) bool
- func IsProcessRunning(proc *os.Process) bool
- func IsServiceRunning(cfg *config.Instance) bool
- func IsTruthy(s string) bool
- func IsValidExtension(ext string) bool
- func IsZip(filePath string) bool
- func ListZip(filePath string) ([]string, error)
- func MapKeys[K comparable, V any](m map[K]V) []K
- func MatchSystemFile(cfg *config.Instance, pl platforms.Platform, systemID string, path string) bool
- func MaybeJSON(data []byte) bool
- func NormalizePathForComparison(path string) string
- func PadNumber(num, width int) string
- func ParseCustomLaunchers(pl platforms.Platform, customLaunchers []config.LaunchersCustom) []platforms.Launcher
- func PathHasPrefix(path, root string) bool
- func PathIsLauncher(cfg *config.Instance, pl platforms.Platform, l *platforms.Launcher, ...) bool
- func PathToLaunchers(cfg *config.Instance, pl platforms.Platform, path string) []platforms.Launcher
- func PlayConfiguredSound(path string, enabled bool, defaultSound []byte, soundName string)
- func RandSeq(n int) (string, error)
- func RandomElem[T any](xs []T) (T, error)
- func RandomInt(maxVal int) (int, error)
- func ScanSteamApps(steamDir string) ([]platforms.ScanResult, error)
- func ScanSteamShortcuts(steamDir string) ([]platforms.ScanResult, error)
- func SpawnDaemon(cfg *config.Instance) (cleanup func(), err error)
- func TokensEqual(a, b *tokens.Token) bool
- func WaitForAPI(cfg *config.Instance, maxWaitTime, checkInterval time.Duration) bool
- func WaitForInternet(maxTries int) bool
- func YesNoPrompt(label string, def bool) bool
- type CommandExecutor
- type LaunchParams
- type LauncherCache
- func (lc *LauncherCache) GetAllLaunchers() []platforms.Launcher
- func (lc *LauncherCache) GetLaunchersBySystem(systemID string) []platforms.Launcher
- func (lc *LauncherCache) Initialize(pl platforms.Platform, cfg *config.Instance)
- func (lc *LauncherCache) Refresh(pl platforms.Platform, cfg *config.Instance)
- type PathInfo
- type RealCommandExecutor
- type RegexCache
- type Service
- func (s *Service) Pid() (int, error)
- func (s *Service) Restart() error
- func (s *Service) Running() bool
- func (s *Service) ServiceHandler(cmd *string) error
- func (s *Service) Start() error
- func (s *Service) Stop() error
- func (s *Service) WaitForAPI(cfg *config.Instance, maxWait, checkInterval time.Duration) error
- type ServiceArgs
- type ServiceEntry
Constants ¶
const ( // ClockSourceSystem indicates the timestamp came from a system clock that appeared reliable. // This could be NTP, RTC, or manually set - we don't distinguish at record creation time. ClockSourceSystem = "system" // ClockSourceEpoch indicates the timestamp came from an unreliable clock (year < 2024). // Common on MiSTer devices that boot without RTC and haven't synced NTP yet. ClockSourceEpoch = "epoch" // ClockSourceHealed indicates the timestamp was mathematically reconstructed. // Original timestamp was unreliable, but was later corrected using: // TrueTimestamp = TrueBootTime + MonotonicOffset ClockSourceHealed = "healed" )
ClockSource values indicate how a timestamp was determined
const ( // MinReliableYear is the earliest year considered valid for the system clock. // Zaparoo Core v2 was released in 2024 - any earlier date indicates an unset clock. MinReliableYear = 2024 )
Variables ¶
var GlobalLauncherCache = &LauncherCache{}
GlobalLauncherCache is the singleton instance used throughout the application.
var GlobalRegexCache = NewRegexCache()
GlobalRegexCache is the singleton instance used throughout the application
var ReURI = regexp.MustCompile(`^([a-zA-Z][a-zA-Z0-9+.-]*)://(.+)$`)
Functions ¶
func AlphaMapKeys ¶
func CachedCompile ¶
CachedCompile compiles and caches a dynamic regex pattern. Returns error if pattern is invalid. Only use for runtime patterns - for static patterns, use package-level vars instead.
func CachedMustCompile ¶
CachedMustCompile compiles and caches a dynamic regex pattern. Panics if pattern is invalid. Only use for runtime patterns - for static patterns, use package-level vars instead.
func Contains ¶
func Contains[T comparable](xs []T, x T) bool
Contains returns true if slice contains value.
func CopyFile ¶
CopyFile copies a file from sourcePath to destPath. Optional perm parameter sets file permissions (uses 0644 if not specified).
func DecodeURIIfNeeded ¶ added in v2.7.0
DecodeURIIfNeeded applies URL decoding to URIs based on their scheme - Zaparoo custom schemes (steam://, kodi-*://, etc.): uses virtualpath.ParseVirtualPathStr for full decoding - Standard web schemes (http://, https://): decodes path component only - Other schemes: returns as-is (no decoding) Returns the original URI on decoding errors (graceful fallback) Uses manual parsing to handle malformed URLs gracefully
func DoLaunch ¶
func DoLaunch(params *LaunchParams) error
DoLaunch launches the given path and updates the active media with it if it was successful.
func EnsureDirectories ¶ added in v2.7.0
EnsureDirectories creates the necessary directories for the application. This should be called early during startup, before InitLogging.
func EqualStringSlices ¶ added in v2.7.0
EqualStringSlices compares two string slices for equality
func FilenameFromPath ¶
func FindLauncher ¶
func FindLauncher( cfg *config.Instance, pl platforms.Platform, path string, ) (platforms.Launcher, error)
FindLauncher takes a path and tries to find the best possible match for a launcher, taking into account any allowlist restrictions. Returns the launcher to be used.
func GetAllLocalIPs ¶
func GetAllLocalIPs() []string
GetAllLocalIPs returns all non-loopback private IPv4 addresses
func GetFileSize ¶
func GetLocalIP ¶
func GetLocalIP() string
func GetMd5Hash ¶
func GetSerialDeviceList ¶
func HasUserDir ¶
HasUserDir checks if a "user" directory exists next to the Zaparoo binary and returns true and the absolute path to it. This directory is used as a parent for all platform directories if it exists, for a portable install. The result is cached after the first call for better performance. This function is safe for concurrent use.
func IsClockReliable ¶ added in v2.7.0
IsClockReliable checks if the system clock appears to be set correctly. Returns false if the clock is clearly wrong (e.g., year < 2024). This handles MiSTer's lack of RTC chip - clock often resets to epoch on boot.
func IsProcessRunning ¶ added in v2.7.0
IsProcessRunning checks if a process is still running. Returns false if the process is nil or has terminated.
func IsServiceRunning ¶
func IsValidExtension ¶ added in v2.7.0
IsValidExtension checks if a file extension contains only valid characters Valid extensions contain only alphanumeric characters (and the leading dot) Examples: ".zip" ✓, ".tar" ✓, ".mp3" ✓, ".other thing" ✗, ".file-name" ✗
func MapKeys ¶
func MapKeys[K comparable, V any](m map[K]V) []K
MapKeys returns a list of all keys in a map.
func MatchSystemFile ¶
func MatchSystemFile( cfg *config.Instance, pl platforms.Platform, systemID string, path string, ) bool
MatchSystemFile returns true if a given path is for a given system.
func NormalizePathForComparison ¶ added in v2.7.0
NormalizePathForComparison normalizes a path for cross-platform case-insensitive comparison. Converts to forward slashes and lowercases for consistent matching across all platforms. This handles paths from databases (forward slashes) vs filepath.Join (OS-specific slashes), and ensures case-insensitive matching works for FAT32/exFAT filesystems on all platforms.
func PadNumber ¶ added in v2.7.0
PadNumber formats a number with leading zeros to the specified width. Examples:
- PadNumber(5, 2) → "05"
- PadNumber(42, 4) → "0042"
- PadNumber(123, 2) → "123"
func ParseCustomLaunchers ¶
func PathHasPrefix ¶ added in v2.7.0
PathHasPrefix checks if path is within root directory, handling separator boundaries correctly. This avoids the prefix bug where "c:/roms2/game.bin" would incorrectly match root "c:/roms".
func PathIsLauncher ¶
func PathIsLauncher( cfg *config.Instance, pl platforms.Platform, l *platforms.Launcher, path string, ) bool
PathIsLauncher returns true if a given path matches against any of the criteria defined in a launcher.
func PathToLaunchers ¶
func PathToLaunchers( cfg *config.Instance, pl platforms.Platform, path string, ) []platforms.Launcher
PathToLaunchers is a reverse lookup to match a given path against all possible launchers in a platform. Returns all matched launchers.
func PlayConfiguredSound ¶ added in v2.7.0
PlayConfiguredSound plays a sound based on configuration settings. If enabled is false, no sound is played. If path is empty, plays the default embedded sound. If path is set, plays the custom sound file from that path. Errors are logged but not returned.
func RandomElem ¶
RandomElem picks and returns a random element from a slice.
func RandomInt ¶ added in v2.7.0
RandomInt returns a random integer between 0 and maxVal-1 (inclusive).
func ScanSteamApps ¶
func ScanSteamApps(steamDir string) ([]platforms.ScanResult, error)
func ScanSteamShortcuts ¶
func ScanSteamShortcuts(steamDir string) ([]platforms.ScanResult, error)
func SpawnDaemon ¶ added in v2.7.0
SpawnDaemon spawns a daemon subprocess for service isolation (e.g., TUI mode). It waits for the service API to become available and returns a cleanup function. The cleanup function sends SIGTERM and waits for graceful shutdown with timeout. Returns a no-op cleanup function if service was already running.
func TokensEqual ¶
func WaitForAPI ¶ added in v2.7.0
WaitForAPI waits for the service API to become available. Returns true if API became available, false if timeout reached.
func WaitForInternet ¶
func YesNoPrompt ¶
Types ¶
type CommandExecutor ¶ added in v2.7.0
type CommandExecutor interface {
// Run executes a command and waits for it to complete.
// Returns an error if the command fails to start or exits with non-zero status.
Run(ctx context.Context, name string, args ...string) error
}
CommandExecutor provides an abstraction over exec.Command for testability. This allows commands to be mocked in tests without executing real system commands.
type LaunchParams ¶ added in v2.7.0
type LaunchParams struct {
Platform platforms.Platform
Config *config.Instance
SetActiveMedia func(*models.ActiveMedia)
Launcher *platforms.Launcher
DB *database.Database
Path string
}
LaunchParams contains all dependencies required for launching media.
type LauncherCache ¶
type LauncherCache struct {
// contains filtered or unexported fields
}
LauncherCache provides fast O(1) launcher lookups by system ID. This replaces the expensive O(n*m) pl.Launchers() calls in hot paths.
func (*LauncherCache) GetAllLaunchers ¶
func (lc *LauncherCache) GetAllLaunchers() []platforms.Launcher
GetAllLaunchers returns all cached launchers.
func (*LauncherCache) GetLaunchersBySystem ¶
func (lc *LauncherCache) GetLaunchersBySystem(systemID string) []platforms.Launcher
GetLaunchersBySystem returns all launchers for a specific system ID. Returns nil if no launchers found for the system.
func (*LauncherCache) Initialize ¶
func (lc *LauncherCache) Initialize(pl platforms.Platform, cfg *config.Instance)
Initialize builds the launcher cache from platform launchers. This should be called once at startup after custom launchers are loaded.
type PathInfo ¶
func GetPathInfo ¶
type RealCommandExecutor ¶ added in v2.7.0
type RealCommandExecutor struct{}
RealCommandExecutor uses actual exec.Command to execute system commands. This is the production implementation used in normal operation.
type RegexCache ¶
type RegexCache struct {
// contains filtered or unexported fields
}
RegexCache provides thread-safe caching of compiled regular expressions to avoid repeated compilation overhead for dynamic/runtime patterns.
When to Use ¶
Use CachedCompile for DYNAMIC patterns only:
- Patterns from user configuration (config files, databases)
- Patterns from external sources (CSV files, APIs)
- Patterns that vary at runtime
For STATIC patterns (constant strings), use package-level variables instead:
var myPattern = regexp.MustCompile(`pattern`) // ✅ Static pattern re := helpers.CachedMustCompile(`pattern`) // ❌ Don't use for static
Package-level vars provide:
- Zero runtime overhead (no map lookups)
- Compile-time validation (errors caught at startup)
- Better code organization (patterns visible at top of file)
func NewRegexCache ¶
func NewRegexCache() *RegexCache
NewRegexCache creates a new RegexCache instance
func (*RegexCache) Clear ¶
func (rc *RegexCache) Clear()
Clear removes all cached patterns (useful for testing or memory management)
func (*RegexCache) Compile ¶
func (rc *RegexCache) Compile(pattern string) (*regexp.Regexp, error)
Compile compiles a regex pattern and caches it for future use. If the pattern is already cached, returns the cached version. Returns an error if the pattern cannot be compiled.
func (*RegexCache) MustCompile ¶
func (rc *RegexCache) MustCompile(pattern string) *regexp.Regexp
MustCompile compiles a regex pattern and caches it for future use. If the pattern is already cached, returns the cached version. Panics if the pattern cannot be compiled (same behavior as regexp.MustCompile).
func (*RegexCache) Size ¶
func (rc *RegexCache) Size() int
Size returns the number of cached patterns
type Service ¶
type Service struct {
// contains filtered or unexported fields
}
func NewService ¶
func NewService(args ServiceArgs) (*Service, error)
func (*Service) ServiceHandler ¶
type ServiceArgs ¶
type ServiceArgs struct {
Platform platforms.Platform
Entry ServiceEntry
NoDaemon bool
}