mediascanner

package
v2.11.0 Latest Latest
Warning

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

Go to latest
Published: Apr 27, 2026 License: GPL-3.0 Imports: 26 Imported by: 0

Documentation

Index

Constants

View Source
const (
	PhaseDiscovering     = "discovering"
	PhaseInitializing    = "initializing"
	PhaseCreatingIndexes = "creating_indexes"
	PhaseBuildingCaches  = "building_caches"
)

Variables

View Source
var ErrFsTimeout = errors.New("filesystem operation timed out")

ErrFsTimeout is returned when a filesystem operation exceeds the timeout.

Functions

func AddMediaPath

func AddMediaPath(
	db database.MediaDBI,
	ss *database.ScanState,
	systemID string,
	path string,
	noExt bool,
	stripLeadingNumbers bool,
	cfg *config.Instance,
	mediaType slugs.MediaType,
) (titleIndex, mediaIndex int, err error)

func FindPath

func FindPath(ctx context.Context, path string) (string, error)

FindPath case-insensitively finds a file/folder at a path and returns the actual filesystem case. On case-insensitive filesystems (Windows, macOS), this ensures we get the real case from the filesystem rather than preserving the input case, which prevents case-mismatch issues during string comparisons.

This function recursively normalizes the entire path from root to leaf to ensure all components match the actual filesystem case.

Special handling:

  • Linux: Prefers exact match before case-insensitive match (handles File.txt vs file.txt)
  • Windows: Handles 8.3 short names (PROGRA~1) via fallback to os.Stat
  • All platforms: Works with symlinks, UNC paths, network drives

func FlushScanStateMaps

func FlushScanStateMaps(ss *database.ScanState)

FlushScanStateMaps clears the per-system in-memory maps (TitleIDs, MediaIDs) to free memory after a system finishes indexing.

IMPORTANT: This must only be called BETWEEN systems, never mid-system. Both TitleIDs and MediaIDs hold dedup state for the current system; clearing them while still inside the per-file loop would cause:

  • InsertMediaTitle UNIQUE failures for multi-file titles (e.g. multi-disc games sharing one MediaTitle row), silently dropping the later files
  • In persistent mode, InsertMedia UNIQUE failures for already-existing media, leaving stale MissingMedia entries that get falsely marked missing

Cross-system safety: MediaKey/TitleKey are systemID-prefixed, so clearing these maps between systems can never collide with the next system's keys. In resume/persistent mode the next system's data is reloaded by PopulateScanStateForSystem / PopulatePersistentScanStateForSystem.

Other maps are intentionally NOT cleared:

  • SystemIDs preserved — DO NOT clear (UNIQUE violations with batch inserts)
  • TagIDs / TagTypeIDs preserved — reused across systems
  • MissingMedia preserved — reinitialized per system before loading that system's existing media and finalized immediately after that system ends

func GetFiles

func GetFiles(
	ctx context.Context,
	cfg *config.Instance,
	platform platforms.Platform,
	systemID string,
	path string,
) ([]string, error)

GetFiles searches for all valid games in a given path and returns a list of files. Uses fastwalk for parallel directory traversal with built-in symlink cycle detection. Deep searches .zip files when ZipsAsDirs is enabled.

func NewNamesIndex

func NewNamesIndex(
	ctx context.Context,
	platform platforms.Platform,
	cfg *config.Instance,
	systems []systemdefs.System,
	fdb *database.Database,
	update func(IndexStatus),
	pauser *syncutil.Pauser,
) (int, error)

NewNamesIndex takes a list of systems, indexes all valid game files on disk and writes a name index to the DB.

Overwrites any existing names index but does not clean up old missing files.

Takes a function which will be called with the current status of the index during key steps.

Returns the total number of files indexed.

func PopulatePersistentScanStateForSystem added in v2.11.0

func PopulatePersistentScanStateForSystem(
	ctx context.Context, db database.MediaDBI, ss *database.ScanState, systemID string,
) error

PopulatePersistentScanStateForSystem loads existing Media DBIDs for a system into ss.MissingMedia. As AddMediaPath processes files, found entries are removed. After the system is fully scanned, remaining entries represent missing media. This also populates MediaIDs and TitleIDs via PopulateScanStateForSystem.

func PopulateScanStateForSelectiveIndexing added in v2.7.0

func PopulateScanStateForSelectiveIndexing(
	ctx context.Context, db database.MediaDBI, ss *database.ScanState, systemsToReindex []string,
) error

PopulateScanStateForSelectiveIndexing populates scan state for selective indexing with optimized loading. Uses true lazy loading for Systems/TagTypes (via UNIQUE constraints) and minimal data loading for MediaTitles/Media (only systems NOT being reindexed) to dramatically improve performance.

func PopulateScanStateForSystem added in v2.9.1

func PopulateScanStateForSystem(
	ctx context.Context, db database.MediaDBI, ss *database.ScanState, systemID string,
) error

PopulateScanStateForSystem loads the existing titles and media for a single system into the scan state. This is called lazily during resume, just before processing each system.

This function is safe to call multiple times for different systems - it appends to the existing TitleIDs and MediaIDs maps.

func PopulateScanStateFromDB added in v2.7.0

func PopulateScanStateFromDB(ctx context.Context, db database.MediaDBI, ss *database.ScanState) error

PopulateScanStateFromDB initializes the scan state with existing database IDs when resuming an interrupted indexing operation

func SeedCanonicalTags added in v2.7.0

func SeedCanonicalTags(db database.MediaDBI, ss *database.ScanState) error

SeedCanonicalTags seeds the database with canonical GameDataBase-style hierarchical tags. Tags follow the format: category:subcategory:value (e.g., "genre:sports:wrestling", "players:2:vs") Tag definitions are in tags.go for centralized management.

NOTE: This function ALWAYS uses non-batch mode (prepared statements) because the canonical tag dataset contains many entries and using batch mode with fail-fast behavior would cause issues. Prepared statements handle this better.

Types

type IndexStatus

type IndexStatus struct {
	SystemID string
	Phase    string // PhaseDiscovering, PhaseInitializing, or empty during indexing
	Total    int
	Step     int
	Files    int
}

type MediaPathFragments

type MediaPathFragments struct {
	Path       string
	FileName   string
	Title      string
	Slug       string
	SlugTokens []string
	Ext        string
	Tags       []string
}

func GetPathFragments

func GetPathFragments(params PathFragmentParams) MediaPathFragments

type PathFragmentKey added in v2.7.0

type PathFragmentKey struct {
	Path                string
	FilenameTags        bool
	StripLeadingNumbers bool
}

type PathFragmentParams added in v2.7.0

type PathFragmentParams struct {
	Config              *config.Instance
	Path                string
	SystemID            string
	MediaType           slugs.MediaType // Pre-resolved media type; skips systemdefs lookup if set
	NoExt               bool
	StripLeadingNumbers bool
}

PathFragmentParams contains parameters for GetPathFragments.

type PathResult

type PathResult struct {
	Path   string
	System systemdefs.System
}

func GetSystemPaths

func GetSystemPaths(
	ctx context.Context,
	cfg *config.Instance,
	platform platforms.Platform,
	rootFolders []string,
	systems []systemdefs.System,
) []PathResult

Jump to

Keyboard shortcuts

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