Skip to content

Catch-up P1: resolve persisted M3U archive metadata into playback timeline #285

Description

@MrFr3di

Parent: #184
Follows: #277 / PR #280

Objective

Implement Slice E for M3U provider catch-up only: consume the catch-up metadata MuxTV already parses and persists, normalize the supported M3U dialect into the provider-neutral PlaybackIntent / ResolvedPlaybackTimeline contract, and keep provider URL/template semantics out of Media3 and presentation.

Confirmed current gap

The data already exists end-to-end through ingest/import/persistence:

StreamingM3uParser -> CatalogImportEntry -> ProviderChannelEntity

with:

  • catchupMode;
  • catchupSource;
  • catchupDays;
  • catchupCorrection.

No Room migration is required.

The current PlaybackCatalogDao/RoomPlaybackCatalog access projection does not carry these fields into archive resolution, so the metadata is persisted but cannot currently drive provider-neutral catch-up playback semantics.

Evidence-backed first dialect

Use the repository-owned sanitized corpus before adding production behavior. Current fixture:

catalog/ingest/src/test/resources/compatibility/m3u/catchup/catchup-metadata.m3u

locks an M3U form using:

  • catchup="append";
  • catchup-source="?utc={utc}...";
  • catchup-days="7";
  • catchup-correction="+2.0".

Do not add guessed catch-up dialects/templates without a compatibility fixture first.

Ownership / architecture

TDD sequence

  1. RED JVM contract test first for the repository-owned append + {utc} fixture semantics.
  2. Minimal provider-specific normalizer/resolver only.
  3. Deterministic UTC retention/correction math with typed unavailable outcomes for requests outside retention.
  4. Carry only the minimum safe persisted metadata needed to the resolution boundary; no raw secret-bearing generated URL in diagnostics/toString.
  5. Keep transport materialization inside the existing provider/catalog access path.
  6. Exact-head host validation before merge; no new Android AVD.

Acceptance

  • PlaybackIntent.Live cannot accidentally select an archive template;
  • supported M3U catch-up programme/position intents resolve deterministically from explicit UTC epoch values;
  • retention window derives from persisted catchupDays and cannot be escaped by rounding/correction;
  • correction parsing/math is deterministic and bounded;
  • unsupported/malformed mode/template returns typed secret-free unavailable result;
  • no locator/query/token/Cookie/Authorization value enters logs, UI semantics or public diagnostics;
  • no Room schema change;
  • no second player/seek/retry owner;
  • existing Live playback remains behavior-identical.

Non-goals

Xtream catch-up, Guide launch UI, local timeshift, DVR, VOD/Series, Media3 mechanics, buffer tuning, new provider framework, new Gradle infrastructure module, third persistent AVD.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions