annie.app_state =============== .. py:module:: annie.app_state .. autoapi-nested-parse:: The composition root: the one place that wires the backend together for the UI. It sits above every package: it builds the source registry, the scan, the review store and the background services (rendering, conversion, previews) from :mod:`annie.dataset`, :mod:`annie.media` and :mod:`annie.parsers`, and the UI (:mod:`annie.pages`, ``app.py``) reaches them through :data:`state`. Nothing below it imports it. Holds the configured :class:`~annie.sources.SourceRegistry`, the cached scan manifest (Browse/Annotator are pure consumers of it), the review store, the render service, and session-only UI settings (row heights). Adding or removing a source re-runs the scan in place, so there is no Scan button. Sources are **session-only**: the registry is seeded from the ``ANNIE_*`` environment variables on startup and otherwise lives for the process lifetime. Curation (verdicts, notes, annotator selection) and protagonist corrections persist independently in SQLite / the ``_manual`` CSV. Attributes ---------- .. autoapisummary:: annie.app_state.state Classes ------- .. autoapisummary:: annie.app_state.UiSettings annie.app_state.AppState Functions --------- .. autoapisummary:: annie.app_state.seed_registry Module Contents --------------- .. py:class:: UiSettings Session-only UI preferences set on the Settings tab. .. attribute:: browse_row_height Media height (px) of a Browse row's thumbnail/strip/render. .. attribute:: annotator_row_height Max media height (px) of an Annotator row; its boxes flex to share the row width and only hit this cap on very wide screens. .. attribute:: auto_scroll Whether reaching the bottom of Browse / Annotator reveals the next page automatically, instead of waiting for a "Show more" click. .. attribute:: page_size How many rows one page reveals, whether auto-scrolled or clicked. .. attribute:: embed_ttl_seconds How long an embedded clip stays on a row before it reverts to its placeholder, freeing the memory the browser holds for it. .. attribute:: unload_after_seconds How long a row may sit off screen before its preview frames are dropped; they are decoded again when it scrolls back. .. attribute:: grid_thumb_height Media height (px) of a Browse **grid** box (Quick selection view); its width is derived 16:9. .. attribute:: grid_page_size How many grid boxes one page reveals — larger than ``page_size`` because a grid box is a single cheap frame. .. attribute:: grid_unload_after_seconds Off-screen TTL for grid boxes; shorter than ``unload_after_seconds`` since the grid packs many videos on screen. .. py:function:: seed_registry() -> annie.dataset.sources.SourceRegistry Build the initial registry from the ``ANNIE_*`` environment variables. .. py:class:: AppState Mutable application state shared between tabs. .. attribute:: registry The configured data sources (the dataset definition). .. attribute:: scan The most recent scan result, recomputed on every source change. .. attribute:: store The SQLite review-status store. .. attribute:: renderer The render-job service. .. attribute:: converter The audio/video re-encode batch runner. .. attribute:: audio_cache Probed audio-stream presence per video id (lazy; see Browse). .. attribute:: frames_cache Decoded frame count per video id (lazy; see Browse). .. attribute:: ui Session-only UI preferences. .. attribute:: active_config The dataset config file currently loaded, or ``None`` for the env-seeded / blank dataset. Lets the Dataset tab show it as selected. .. attribute:: scanned_tracks Each video's protagonist as scanned (the heuristic CSV), before the review DB's corrections are layered over it; lets a DB switch start over. .. attribute:: previews The shared preview loader (bounded, newest-first, cached decoding). .. attribute:: scanning Whether a scan is running right now (start-up scan included), so every page can show it as busy. .. py:method:: restore_last_config() -> pathlib.Path | None Reopen the config remembered from the previous run, with its review database. This is what lets a user close Annie and, on the next start, land straight back in their dataset with all their progress — no need to re-pick the config. A config that has gone missing or fails to load is skipped (and logged), leaving the current dataset in place. :returns: The config path that was restored, or ``None`` if nothing was. .. py:method:: rescan() -> None Rebuild the manifest from the current registry (after a source change). Also clears the audio and frame-count caches so that any replaced or renamed video files are re-probed on the next Browse render. .. py:method:: set_store(db_path: pathlib.Path) -> None Replace the active review store with one backed by ``db_path``. The file is created (with the schema applied) if it does not exist yet. Call this whenever the user changes the persistence target — either by loading a config that embeds a ``"db"`` path, or by choosing a DB file in the Persistence block on the Dataset tab. The new DB's protagonist corrections replace the previous DB's on the scanned videos straight away, instead of only after the next rescan or restart. :param db_path: Absolute path to the SQLite file to open. .. py:method:: review_lookup() -> collections.abc.Callable[[str], annie.dataset.filtering.ReviewState] Read every review state in one query and return a per-key lookup. For a pass over many videos (e.g. the Browse filter); the lookup answers exactly like :meth:`review_state` but from a snapshot taken now. :returns: A function mapping a video key to its :class:`~annie.filtering.ReviewState`. .. py:method:: review_state(key: str) -> annie.dataset.filtering.ReviewState Return the filtering-facing review state for a video (default liked). :param key: The video key. :returns: A :class:`~annie.filtering.ReviewState`; videos with no stored row are liked (good) with no note and not queued for the Annotator. .. py:data:: state The single shared state instance. The initial scan is deferred to app startup (see :mod:`annie.app`) so imports stay fast.