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
- RED JVM contract test first for the repository-owned
append + {utc} fixture semantics.
- Minimal provider-specific normalizer/resolver only.
- Deterministic UTC retention/correction math with typed unavailable outcomes for requests outside retention.
- Carry only the minimum safe persisted metadata needed to the resolution boundary; no raw secret-bearing generated URL in diagnostics/toString.
- Keep transport materialization inside the existing provider/catalog access path.
- 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.
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/ResolvedPlaybackTimelinecontract, 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 -> ProviderChannelEntitywith:
catchupMode;catchupSource;catchupDays;catchupCorrection.No Room migration is required.
The current
PlaybackCatalogDao/RoomPlaybackCatalogaccess 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.m3ulocks 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
catalog:refresh(current precedent:XtreamPlaybackReferenceResolver);player:apiremains provider-neutral and ownsPlaybackIntent/ResolvedPlaybackTimeline;catalog:apiandplayer:apimust not gain a dependency cycle;player:media3must not parse M3U/Kodi templates;TDD sequence
append + {utc}fixture semantics.Acceptance
PlaybackIntent.Livecannot accidentally select an archive template;catchupDaysand cannot be escaped by rounding/correction;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.